Add check_symbols.py for ETH perpetuals filtering and enhance backtester with size handling
- Introduced `check_symbols.py` to load and filter ETH perpetual markets from the OKX exchange using CCXT. - Updated the backtester to normalize signals to a 5-tuple format, incorporating size management for trades. - Enhanced portfolio functions to support variable size and leverage adjustments based on initial capital. - Added a new method in `CryptoQuantClient` for chunked historical data fetching to avoid API limits. - Improved market symbol normalization in `market.py` to handle different formats. - Updated regime strategy parameters based on recent research findings for optimal performance.
This commit is contained in:
@@ -74,75 +74,35 @@ def run_long_short_portfolio(
|
||||
sl_stop: float | None,
|
||||
tp_stop: float | None,
|
||||
sl_trail: bool,
|
||||
leverage: int
|
||||
leverage: int,
|
||||
size: pd.Series | float = 1.0,
|
||||
size_type: str = 'value' # Changed to 'value' to support reversals/sizing
|
||||
) -> vbt.Portfolio:
|
||||
"""
|
||||
Run a portfolio supporting both long and short positions.
|
||||
|
||||
Runs two separate portfolios (long and short) and combines results.
|
||||
Each gets half the capital.
|
||||
|
||||
Args:
|
||||
close: Close price series
|
||||
long_entries: Long entry signals
|
||||
long_exits: Long exit signals
|
||||
short_entries: Short entry signals
|
||||
short_exits: Short exit signals
|
||||
init_cash: Initial capital
|
||||
fees: Transaction fee percentage
|
||||
slippage: Slippage percentage
|
||||
freq: Data frequency string
|
||||
sl_stop: Stop loss percentage
|
||||
tp_stop: Take profit percentage
|
||||
sl_trail: Enable trailing stop loss
|
||||
leverage: Leverage multiplier
|
||||
|
||||
Returns:
|
||||
VectorBT Portfolio object (long portfolio, short stats logged)
|
||||
Uses VectorBT's native support for short_entries/short_exits
|
||||
to simulate a single unified portfolio.
|
||||
"""
|
||||
effective_cash = init_cash * leverage
|
||||
half_cash = effective_cash / 2
|
||||
|
||||
# Run long-only portfolio
|
||||
long_pf = vbt.Portfolio.from_signals(
|
||||
# If size is passed as value (USD), we don't scale it by leverage here
|
||||
# The backtester has already scaled it by init_cash.
|
||||
# If using 'value', vbt treats it as "Amount of CASH to use for the trade"
|
||||
|
||||
return vbt.Portfolio.from_signals(
|
||||
close=close,
|
||||
entries=long_entries,
|
||||
exits=long_exits,
|
||||
direction='longonly',
|
||||
init_cash=half_cash,
|
||||
short_entries=short_entries,
|
||||
short_exits=short_exits,
|
||||
init_cash=effective_cash,
|
||||
fees=fees,
|
||||
slippage=slippage,
|
||||
freq=freq,
|
||||
sl_stop=sl_stop,
|
||||
tp_stop=tp_stop,
|
||||
sl_trail=sl_trail,
|
||||
size=1.0,
|
||||
size_type='percent',
|
||||
size=size,
|
||||
size_type=size_type,
|
||||
)
|
||||
|
||||
# Run short-only portfolio
|
||||
short_pf = vbt.Portfolio.from_signals(
|
||||
close=close,
|
||||
entries=short_entries,
|
||||
exits=short_exits,
|
||||
direction='shortonly',
|
||||
init_cash=half_cash,
|
||||
fees=fees,
|
||||
slippage=slippage,
|
||||
freq=freq,
|
||||
sl_stop=sl_stop,
|
||||
tp_stop=tp_stop,
|
||||
sl_trail=sl_trail,
|
||||
size=1.0,
|
||||
size_type='percent',
|
||||
)
|
||||
|
||||
# Log both portfolio stats
|
||||
# TODO: Implement proper portfolio combination
|
||||
logger.info(
|
||||
"Long portfolio: %.2f%% return, Short portfolio: %.2f%% return",
|
||||
long_pf.total_return().mean() * 100,
|
||||
short_pf.total_return().mean() * 100
|
||||
)
|
||||
|
||||
return long_pf
|
||||
|
||||
Reference in New Issue
Block a user