新增加项目文件,
This commit is contained in:
187
strategy.py
Normal file
187
strategy.py
Normal file
@@ -0,0 +1,187 @@
|
||||
"""
|
||||
行情策略管理模块 - 支持多种策略
|
||||
"""
|
||||
import logging
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
from quote_manager import QuoteManager, DataSource
|
||||
from logger_utils_new import log_info, log_warning, log_error, log_trigger, log_debug, setup_logger, LOG_STYLES
|
||||
from abc import ABC, abstractmethod
|
||||
from enum import Enum, auto
|
||||
|
||||
|
||||
class StrategyType(Enum):
|
||||
TU_STRATEGY = auto() # 土策略
|
||||
BREAKOUT_STRATEGY = auto() # 突破策略
|
||||
MEAN_REVERSION_STRATEGY = auto() # 均值回归策略
|
||||
|
||||
class TradingStrategy(ABC):
|
||||
def __init__(self, quote_manager):
|
||||
self.quote_manager = quote_manager
|
||||
self.history_data = {}
|
||||
self.STOP_LOSS = 0.03
|
||||
self.COMMISSION = 0.0003
|
||||
self.MIN_TRADE_AMOUNT = 1e7
|
||||
@abstractmethod
|
||||
def _analyze_signal(self, quote_data):
|
||||
"""分析交易信号"""
|
||||
pass
|
||||
|
||||
class TuStrategy(TradingStrategy):
|
||||
"""土策略实现"""
|
||||
def analyze_signal(self, quote_data):
|
||||
# 现有的土策略分析逻辑
|
||||
# ... 保留原有代码 ...
|
||||
signal = {
|
||||
'code': quote_data['TS_CODE'],
|
||||
'signal': 'buy' if quote_data['PRICE'] < quote_data['OPEN'] else 'sell',
|
||||
'price': quote_data['PRICE'],
|
||||
'volume': quote_data['VOLUME'],
|
||||
'timestamp': pd.Timestamp.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
}
|
||||
return signal
|
||||
|
||||
class BreakoutStrategy(TradingStrategy):
|
||||
"""突破策略实现"""
|
||||
def analyze_signal(self, quote_data):
|
||||
# 实现突破策略逻辑
|
||||
# ... 新增代码 ...
|
||||
signal = {
|
||||
'code': quote_data['TS_CODE'],
|
||||
'signal': 'buy' if quote_data['PRICE'] > quote_data['OPEN'] else'sell',
|
||||
'price': quote_data['PRICE'],
|
||||
'volume': quote_data['VOLUME'],
|
||||
'timestamp': pd.Timestamp.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
}
|
||||
return signal
|
||||
|
||||
class StrategyManager:
|
||||
def __init__(self, quote_manager):
|
||||
self.quote_manager = quote_manager
|
||||
self.strategies = {
|
||||
StrategyType.TU_STRATEGY: TuStrategy(quote_manager),
|
||||
StrategyType.BREAKOUT_STRATEGY: BreakoutStrategy(quote_manager)
|
||||
}
|
||||
self.current_strategy = StrategyType.TU_STRATEGY # 默认策略
|
||||
|
||||
def set_strategy(self, strategy_type):
|
||||
"""设置当前使用的策略"""
|
||||
if strategy_type in self.strategies:
|
||||
self.current_strategy = strategy_type
|
||||
return True
|
||||
return False
|
||||
|
||||
def monitor_stocks(self, stock_codes):
|
||||
"""使用当前策略监控股票"""
|
||||
strategy = self.strategies[self.current_strategy]
|
||||
return strategy.monitor_stocks(stock_codes)
|
||||
|
||||
|
||||
class TradingStrategy(ABC):
|
||||
def __init__(self, quote_manager):
|
||||
self.quote_manager = QuoteManager()
|
||||
|
||||
def monitor_stocks(self, stock_codes):
|
||||
"""监控股票行情"""
|
||||
try:
|
||||
quotes = self.quote_manager.get_realtime_quotes(stock_codes)
|
||||
log_info(f"行情更新: {pd.Timestamp.now()}")
|
||||
|
||||
signals = []
|
||||
for code, data in quotes.items():
|
||||
signal = self._analyze_signal(data)
|
||||
log_info(f"{code}: 最新价 {data['PRICE']} 成交量 {data['VOLUME']}")
|
||||
signals.append({
|
||||
'code': code,
|
||||
'signal': signal,
|
||||
'price': data['PRICE'],
|
||||
'volume': data['VOLUME'],
|
||||
'timestamp': pd.Timestamp.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
})
|
||||
|
||||
|
||||
return signals
|
||||
|
||||
except Exception as e:
|
||||
log_error(f"获取行情失败: {str(e)}")
|
||||
return []
|
||||
|
||||
def __init__(self, quote_manager):
|
||||
self.quote_manager = quote_manager
|
||||
self.history_data = {}
|
||||
self.STOP_LOSS = 0.03 # 止损比例
|
||||
self.COMMISSION = 0.0003 # 单边佣金
|
||||
self.MIN_TRADE_AMOUNT = 1e7 # 最小成交金额
|
||||
|
||||
def _calculate_slope(self, x):
|
||||
"""计算斜率"""
|
||||
if len(x) < 2:
|
||||
return np.nan
|
||||
|
||||
n = len(x)
|
||||
sum_x = (n - 1) * n / 2
|
||||
sum_xx = (n - 1) * n * (2 * n - 1) / 6
|
||||
|
||||
sum_y = np.sum(x)
|
||||
sum_xy = np.sum(np.arange(n) * x)
|
||||
|
||||
denom = n * sum_xx - sum_x * sum_x
|
||||
if denom == 0:
|
||||
return np.nan
|
||||
|
||||
return (n * sum_xy - sum_x * sum_y) / denom
|
||||
|
||||
def _update_history_data(self, code, data):
|
||||
"""更新历史数据"""
|
||||
if code not in self.history_data:
|
||||
self.history_data[code] = []
|
||||
self.history_data[code].append(data)
|
||||
# 只保留最近30天数据
|
||||
if len(self.history_data[code]) > 30:
|
||||
self.history_data[code] = self.history_data[code][-30:]
|
||||
return pd.DataFrame(self.history_data[code])
|
||||
|
||||
def _analyze_signal(self, quote_data):
|
||||
"""基于土策略分析交易信号"""
|
||||
code = quote_data['TS_CODE']
|
||||
df = self._update_history_data(code, quote_data)
|
||||
|
||||
if len(df) < 25: # 确保有足够数据计算指标
|
||||
return 'HOLD'
|
||||
|
||||
# 计算技术指标
|
||||
df = df.sort_values('TRADE_DATE')
|
||||
df['X_1'] = df['LOW'].rolling(10, min_periods=5).min()
|
||||
df['X_2'] = df['HIGH'].rolling(25, min_periods=10).max()
|
||||
df['X_6'] = ((df['CLOSE'] - df['X_1']) / (df['X_2'].replace(0, np.nan) - df['X_1']) * 4)
|
||||
df['X_6'] = df['X_6'].ewm(span=4, adjust=False).mean().shift(1)
|
||||
|
||||
# 信号过滤条件
|
||||
df['X_7'] = df['X_6'].rolling(5).apply(
|
||||
lambda x: 0 if (np.diff(x > 3.5) == 1).any() else 1, raw=True
|
||||
).fillna(1)
|
||||
|
||||
# 动量计算
|
||||
df['X_10'] = df['CLOSE'].pct_change(2).shift(1) * 100
|
||||
df['X_43'] = df['X_10'].rolling(2).sum() * df['X_7']
|
||||
|
||||
# 复合指标
|
||||
ema_open_12 = df['OPEN'].ewm(span=12, adjust=False).mean()
|
||||
df['X_15'] = df['X_7'] * (df['OPEN'] - ema_open_12) / ema_open_12 * 200
|
||||
|
||||
# 斜率计算
|
||||
df['X_41'] = df['X_15'].rolling(2).apply(self._calculate_slope)
|
||||
df['X_42'] = df['X_6'].rolling(2).apply(self._calculate_slope)
|
||||
|
||||
# 最终土值计算
|
||||
df['tu_value'] = (df['X_41'] * 0.02 - df['X_42'] * df['X_7']) * df['X_7']
|
||||
|
||||
# 过滤条件
|
||||
current = df.iloc[-1]
|
||||
if (current['X_43'] > 8 and
|
||||
not current['CODE'].startswith(('313', '314', '315', '688')) and
|
||||
current['AMOUNT'] > self.MIN_TRADE_AMOUNT and
|
||||
not np.isnan(current['tu_value'])):
|
||||
return 'BUY' if current['tu_value'] > 0 else 'SELL'
|
||||
return 'HOLD'
|
||||
Reference in New Issue
Block a user