190 lines
6.4 KiB
Python
190 lines
6.4 KiB
Python
"""
|
||
交易策略 - 趋势跟踪策略定义
|
||
"""
|
||
from typing import Dict, List, Any
|
||
from app.utils.logger import logger
|
||
|
||
|
||
class TrendFollowingStrategy:
|
||
"""趋势跟踪策略"""
|
||
|
||
# 趋势判断规则(1H + 4H)
|
||
TREND_RULES = {
|
||
'bullish': {
|
||
'description': '看涨趋势',
|
||
'conditions': [
|
||
{'name': 'price_above_ma20', 'desc': '价格在MA20上方'},
|
||
{'name': 'ma5_above_ma20', 'desc': 'MA5在MA20上方'},
|
||
{'name': 'macd_positive', 'desc': 'MACD在信号线上方'},
|
||
{'name': 'rsi_above_50', 'desc': 'RSI大于50'}
|
||
]
|
||
},
|
||
'bearish': {
|
||
'description': '看跌趋势',
|
||
'conditions': [
|
||
{'name': 'price_below_ma20', 'desc': '价格在MA20下方'},
|
||
{'name': 'ma5_below_ma20', 'desc': 'MA5在MA20下方'},
|
||
{'name': 'macd_negative', 'desc': 'MACD在信号线下方'},
|
||
{'name': 'rsi_below_50', 'desc': 'RSI小于50'}
|
||
]
|
||
}
|
||
}
|
||
|
||
# 进场规则(5M + 15M)
|
||
ENTRY_RULES = {
|
||
'buy': {
|
||
'description': '做多进场',
|
||
'conditions': [
|
||
{'name': 'rsi_oversold_recovery', 'desc': 'RSI从超卖区回升', 'weight': 2},
|
||
{'name': 'macd_golden_cross', 'desc': 'MACD金叉', 'weight': 2},
|
||
{'name': 'price_break_bb_middle', 'desc': '价格突破布林中轨', 'weight': 1},
|
||
{'name': 'kdj_golden_cross', 'desc': 'KDJ低位金叉', 'weight': 1},
|
||
{'name': 'volume_increase', 'desc': '成交量放大', 'weight': 1}
|
||
],
|
||
'min_score': 3 # 最低触发分数
|
||
},
|
||
'sell': {
|
||
'description': '做空进场',
|
||
'conditions': [
|
||
{'name': 'rsi_overbought_decline', 'desc': 'RSI从超买区回落', 'weight': 2},
|
||
{'name': 'macd_death_cross', 'desc': 'MACD死叉', 'weight': 2},
|
||
{'name': 'price_break_bb_middle_down', 'desc': '价格跌破布林中轨', 'weight': 1},
|
||
{'name': 'kdj_death_cross', 'desc': 'KDJ高位死叉', 'weight': 1},
|
||
{'name': 'volume_increase', 'desc': '成交量放大', 'weight': 1}
|
||
],
|
||
'min_score': 3
|
||
}
|
||
}
|
||
|
||
# 出场规则
|
||
EXIT_RULES = {
|
||
'take_profit': {
|
||
'description': '止盈',
|
||
'conditions': [
|
||
{'name': 'target_reached', 'desc': '达到目标价位'},
|
||
{'name': 'rsi_extreme', 'desc': 'RSI达到极值'},
|
||
{'name': 'trend_reversal', 'desc': '趋势反转信号'}
|
||
]
|
||
},
|
||
'stop_loss': {
|
||
'description': '止损',
|
||
'conditions': [
|
||
{'name': 'price_hit_stop', 'desc': '价格触及止损位'},
|
||
{'name': 'trend_break', 'desc': '趋势破坏'}
|
||
]
|
||
}
|
||
}
|
||
|
||
# 风险管理参数
|
||
RISK_PARAMS = {
|
||
'max_position_size': 0.1, # 最大仓位比例
|
||
'stop_loss_atr_multiplier': 2.0, # 止损 ATR 倍数
|
||
'take_profit_atr_multiplier': 3.0, # 止盈 ATR 倍数
|
||
'max_daily_trades': 5, # 每日最大交易次数
|
||
'min_risk_reward_ratio': 1.5 # 最小风险收益比
|
||
}
|
||
|
||
def __init__(self):
|
||
"""初始化策略"""
|
||
logger.info("趋势跟踪策略初始化完成")
|
||
|
||
def get_trend_rules(self, trend: str) -> Dict[str, Any]:
|
||
"""获取趋势判断规则"""
|
||
return self.TREND_RULES.get(trend, {})
|
||
|
||
def get_entry_rules(self, action: str) -> Dict[str, Any]:
|
||
"""获取进场规则"""
|
||
return self.ENTRY_RULES.get(action, {})
|
||
|
||
def get_exit_rules(self, exit_type: str) -> Dict[str, Any]:
|
||
"""获取出场规则"""
|
||
return self.EXIT_RULES.get(exit_type, {})
|
||
|
||
def calculate_position_size(self, account_balance: float, risk_per_trade: float,
|
||
entry_price: float, stop_loss: float) -> float:
|
||
"""
|
||
计算仓位大小
|
||
|
||
Args:
|
||
account_balance: 账户余额
|
||
risk_per_trade: 单笔风险比例(如 0.02 表示 2%)
|
||
entry_price: 入场价格
|
||
stop_loss: 止损价格
|
||
|
||
Returns:
|
||
建议仓位大小
|
||
"""
|
||
risk_amount = account_balance * risk_per_trade
|
||
price_risk = abs(entry_price - stop_loss)
|
||
|
||
if price_risk == 0:
|
||
return 0
|
||
|
||
position_size = risk_amount / price_risk
|
||
|
||
# 限制最大仓位
|
||
max_position = account_balance * self.RISK_PARAMS['max_position_size'] / entry_price
|
||
position_size = min(position_size, max_position)
|
||
|
||
return round(position_size, 6)
|
||
|
||
def validate_trade(self, entry_price: float, stop_loss: float,
|
||
take_profit: float) -> Dict[str, Any]:
|
||
"""
|
||
验证交易是否符合风险管理规则
|
||
|
||
Args:
|
||
entry_price: 入场价格
|
||
stop_loss: 止损价格
|
||
take_profit: 止盈价格
|
||
|
||
Returns:
|
||
验证结果
|
||
"""
|
||
risk = abs(entry_price - stop_loss)
|
||
reward = abs(take_profit - entry_price)
|
||
|
||
if risk == 0:
|
||
return {
|
||
'valid': False,
|
||
'reason': '止损距离为0',
|
||
'risk_reward_ratio': 0
|
||
}
|
||
|
||
risk_reward_ratio = reward / risk
|
||
|
||
if risk_reward_ratio < self.RISK_PARAMS['min_risk_reward_ratio']:
|
||
return {
|
||
'valid': False,
|
||
'reason': f'风险收益比({risk_reward_ratio:.2f})低于最低要求({self.RISK_PARAMS["min_risk_reward_ratio"]})',
|
||
'risk_reward_ratio': risk_reward_ratio
|
||
}
|
||
|
||
return {
|
||
'valid': True,
|
||
'reason': '符合风险管理规则',
|
||
'risk_reward_ratio': risk_reward_ratio
|
||
}
|
||
|
||
def get_strategy_description(self) -> str:
|
||
"""获取策略描述"""
|
||
return """
|
||
## 趋势跟踪策略
|
||
|
||
### 核心理念
|
||
顺势而为,在大周期确认趋势后,在小周期寻找最佳进场点。
|
||
|
||
### 趋势判断(4H + 1H)
|
||
- 看涨:价格在MA20上方,MA5>MA20,MACD>信号线,RSI>50
|
||
- 看跌:价格在MA20下方,MA5<MA20,MACD<信号线,RSI<50
|
||
|
||
### 进场信号(15M + 5M)
|
||
- 做多:RSI超卖回升、MACD金叉、突破布林中轨、KDJ低位金叉
|
||
- 做空:RSI超买回落、MACD死叉、跌破布林中轨、KDJ高位死叉
|
||
|
||
### 风险管理
|
||
- 止损:2倍ATR
|
||
- 止盈:3倍ATR
|
||
- 最小风险收益比:1.5
|
||
"""
|