14564
This commit is contained in:
91
mexc/30分钟.py
91
mexc/30分钟.py
@@ -41,6 +41,57 @@ from models.mexc import Mexc30
|
||||
|
||||
# ========================= 工具函数 =========================
|
||||
|
||||
# 交易对的最小价格单位(tick size)配置
|
||||
# 格式:交易对符号 -> 最小单位
|
||||
TICK_SIZE_MAP = {
|
||||
'SOLUSDT': 0.01,
|
||||
'BTCUSDT': 0.1,
|
||||
'ETHUSDT': 0.01,
|
||||
'BNBUSDT': 0.01,
|
||||
# 可以根据需要添加更多交易对
|
||||
}
|
||||
|
||||
# 默认最小单位(如果交易对不在配置中)
|
||||
DEFAULT_TICK_SIZE = 0.01
|
||||
|
||||
|
||||
def get_tick_size(symbol: str) -> float:
|
||||
"""
|
||||
获取交易对的最小价格单位
|
||||
:param symbol: 交易对符号,如 'SOLUSDT'
|
||||
:return: 最小单位,如 0.01
|
||||
"""
|
||||
return TICK_SIZE_MAP.get(symbol.upper(), DEFAULT_TICK_SIZE)
|
||||
|
||||
|
||||
def adjust_price_for_trade(price: float, direction: str, symbol: str = 'SOLUSDT') -> float:
|
||||
"""
|
||||
根据交易方向调整价格,考虑买卖价差
|
||||
|
||||
买入(开多/平空):价格 + tick_size
|
||||
卖出(开空/平多):价格 - tick_size
|
||||
|
||||
:param price: 原始价格(K线开盘价或收盘价)
|
||||
:param direction: 交易方向,'long' 表示买入,'short' 表示卖出
|
||||
:param symbol: 交易对符号,用于获取最小单位
|
||||
:return: 调整后的价格
|
||||
"""
|
||||
tick_size = get_tick_size(symbol)
|
||||
|
||||
if direction == 'long':
|
||||
# 买入:价格 + tick_size
|
||||
adjusted = price + tick_size
|
||||
elif direction == 'short':
|
||||
# 卖出:价格 - tick_size
|
||||
adjusted = price - tick_size
|
||||
else:
|
||||
# 未知方向,返回原价
|
||||
adjusted = price
|
||||
|
||||
# 确保价格不会为负
|
||||
return max(adjusted, tick_size)
|
||||
|
||||
|
||||
def is_bullish(c): # 阳线
|
||||
return float(c['close']) > float(c['open'])
|
||||
|
||||
@@ -109,7 +160,7 @@ def get_data_by_date(model, date_str: str):
|
||||
|
||||
# ========================= 回测逻辑 =========================
|
||||
|
||||
def backtest_15m_trend_optimized(dates: List[str]):
|
||||
def backtest_15m_trend_optimized(dates: List[str], symbol: str = 'SOLUSDT'):
|
||||
"""
|
||||
回测策略逻辑:
|
||||
1. 开仓条件(信号出现时,下一根K线开盘价开仓):
|
||||
@@ -182,7 +233,9 @@ def backtest_15m_trend_optimized(dates: List[str]):
|
||||
if current_position is None:
|
||||
if direction:
|
||||
# 信号出现(prev和curr形成信号),在下一根K线(next_bar)的开盘价开仓
|
||||
entry_price = float(next_bar['open'])
|
||||
# 应用买卖价差:买入(开多)时价格+0.01,卖出(开空)时价格-0.01
|
||||
raw_price = float(next_bar['open'])
|
||||
entry_price = adjust_price_for_trade(raw_price, direction, symbol)
|
||||
current_position = {
|
||||
'direction': direction,
|
||||
'signal': stats[signal_key]['name'],
|
||||
@@ -192,7 +245,7 @@ def backtest_15m_trend_optimized(dates: List[str]):
|
||||
}
|
||||
consecutive_opposite_count = 0 # 重置连续反色计数
|
||||
stats[signal_key]['count'] += 1
|
||||
logger.debug(f"开仓: {stats[signal_key]['name']} {'做多' if direction == 'long' else '做空'} @ {entry_price:.2f}")
|
||||
logger.debug(f"开仓: {stats[signal_key]['name']} {'做多' if direction == 'long' else '做空'} @ {entry_price:.2f} (原始价格: {raw_price:.2f})")
|
||||
idx += 1
|
||||
continue
|
||||
|
||||
@@ -203,7 +256,11 @@ def backtest_15m_trend_optimized(dates: List[str]):
|
||||
# 1. 反向信号 -> 下一根K线开盘价平仓并反手开仓
|
||||
# 策略:遇到反向信号(如持有多单时遇到阴包阳),平仓并反手开仓
|
||||
if direction and direction != pos_dir:
|
||||
exit_price = float(next_bar['open'])
|
||||
# 平仓:持有多单时卖出(价格-0.01),持有空单时买入(价格+0.01)
|
||||
raw_exit_price = float(next_bar['open'])
|
||||
exit_direction = 'short' if pos_dir == 'long' else 'long' # 平仓方向与持仓方向相反
|
||||
exit_price = adjust_price_for_trade(raw_exit_price, exit_direction, symbol)
|
||||
|
||||
diff = (exit_price - current_position['entry_price']) if pos_dir == 'long' else (
|
||||
current_position['entry_price'] - exit_price)
|
||||
trades.append({
|
||||
@@ -218,17 +275,19 @@ def backtest_15m_trend_optimized(dates: List[str]):
|
||||
stats[pos_sig_key]['total_profit'] += diff
|
||||
if diff > 0: stats[pos_sig_key]['wins'] += 1
|
||||
|
||||
# 反手开仓(下一根K线开盘价)
|
||||
# 反手开仓(下一根K线开盘价,应用买卖价差)
|
||||
raw_entry_price = float(next_bar['open'])
|
||||
entry_price = adjust_price_for_trade(raw_entry_price, direction, symbol)
|
||||
current_position = {
|
||||
'direction': direction,
|
||||
'signal': stats[signal_key]['name'],
|
||||
'signal_key': signal_key,
|
||||
'entry_price': exit_price,
|
||||
'entry_price': entry_price,
|
||||
'entry_time': next_bar['id']
|
||||
}
|
||||
consecutive_opposite_count = 0 # 重置连续反色计数
|
||||
stats[signal_key]['count'] += 1
|
||||
logger.debug(f"反向信号反手: 平{'做多' if pos_dir == 'long' else '做空'} @ {exit_price:.2f}, 开{'做多' if direction == 'long' else '做空'}")
|
||||
logger.debug(f"反向信号反手: 平{'做多' if pos_dir == 'long' else '做空'} @ {exit_price:.2f} (原始: {raw_exit_price:.2f}), 开{'做多' if direction == 'long' else '做空'} @ {entry_price:.2f} (原始: {raw_entry_price:.2f})")
|
||||
idx += 1
|
||||
continue
|
||||
|
||||
@@ -240,7 +299,9 @@ def backtest_15m_trend_optimized(dates: List[str]):
|
||||
# 如果已经连续两根阴线,下一根K线开盘价平仓
|
||||
if consecutive_opposite_count >= 2:
|
||||
logger.debug(f"平仓: 做多遇到连续两根阴线")
|
||||
exit_price = float(next_bar['open'])
|
||||
# 平多单:卖出,价格 - 0.01
|
||||
raw_exit_price = float(next_bar['open'])
|
||||
exit_price = adjust_price_for_trade(raw_exit_price, 'short', symbol)
|
||||
diff = exit_price - current_position['entry_price']
|
||||
trades.append({
|
||||
'entry_time': datetime.datetime.fromtimestamp(current_position['entry_time'] / 1000),
|
||||
@@ -268,7 +329,9 @@ def backtest_15m_trend_optimized(dates: List[str]):
|
||||
# 如果已经连续两根阳线,下一根K线开盘价平仓
|
||||
if consecutive_opposite_count >= 2:
|
||||
logger.debug(f"平仓: 做空遇到连续两根阳线")
|
||||
exit_price = float(next_bar['open'])
|
||||
# 平空单:买入,价格 + 0.01
|
||||
raw_exit_price = float(next_bar['open'])
|
||||
exit_price = adjust_price_for_trade(raw_exit_price, 'long', symbol)
|
||||
diff = current_position['entry_price'] - exit_price
|
||||
trades.append({
|
||||
'entry_time': datetime.datetime.fromtimestamp(current_position['entry_time'] / 1000),
|
||||
@@ -305,8 +368,12 @@ def backtest_15m_trend_optimized(dates: List[str]):
|
||||
# 尾仓:最后一根收盘价平仓
|
||||
if current_position:
|
||||
last = all_data[-1]
|
||||
exit_price = float(last['close'])
|
||||
pos_dir = current_position['direction']
|
||||
# 平仓:持有多单时卖出(价格-0.01),持有空单时买入(价格+0.01)
|
||||
raw_exit_price = float(last['close'])
|
||||
exit_direction = 'short' if pos_dir == 'long' else 'long' # 平仓方向与持仓方向相反
|
||||
exit_price = adjust_price_for_trade(raw_exit_price, exit_direction, symbol)
|
||||
|
||||
diff = (exit_price - current_position['entry_price']) if pos_dir == 'long' else (
|
||||
current_position['entry_price'] - exit_price)
|
||||
trades.append({
|
||||
@@ -346,7 +413,9 @@ if __name__ == '__main__':
|
||||
print(dates)
|
||||
|
||||
# dates = [f"2025-09-{i}" for i in range(1, 32)]
|
||||
trades, stats = backtest_15m_trend_optimized(dates)
|
||||
# 指定交易对符号,用于获取正确的最小价格单位
|
||||
symbol = 'SOLUSDT'
|
||||
trades, stats = backtest_15m_trend_optimized(dates, symbol=symbol)
|
||||
|
||||
logger.info("===== 每笔交易详情 =====")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user