期货交易策略自动化实现
1. 项目概述
本项目旨在为期货交易客户开发一个自动化交易系统,基于Python实现其交易策略。系统将包含数据获取、策略逻辑、风险控制、订单执行和绩效分析等模块,实现全自动化的期货交易。
2. 系统架构设计
2.1 系统组件
- 数据模块:实时市场数据获取与处理
- 策略模块:交易逻辑实现
- 风控模块:资金管理与风险控制
- 执行模块:订单生成与执行
- 监控模块:实时监控与报警
- 回测模块:历史数据测试与优化
2.2 技术栈
- 编程语言:Python 3.8+
- 数据获取:Tushare、AkShare、API接口
- 数据库:MySQL/PostgreSQL/SQLite
- 可视化:Matplotlib、Plotly、PyQt5
- 并发处理:Asyncio、Multiprocessing
- 部署:Docker、Linux服务器
3. 数据模块实现
3.1 数据获取类
python
import pandas as pd
import numpy as np
import akshare as ak
import tushare as ts
import requests
import time
import json
from datetime import datetime, timedelta
import sqlite3
import logging
class DataFetcher:
def __init__(self, config_path="config.json"):
self.logger = logging.getLogger(__name__)
self.load_config(config_path)
self.setup_database()
def load_config(self, config_path):
"""加载配置文件"""
try:
with open(config_path, 'r') as f:
self.config = json.load(f)
self.logger.info("配置文件加载成功")
except FileNotFoundError:
self.logger.error("配置文件未找到,使用默认配置")
self.config = {
"database": {
"path": "futures_data.db"
},
"data_sources": {
"preferred": "akshare",
"backup": "tushare"
}
}
def setup_database(self):
"""设置数据库连接"""
self.db_path = self.config['database']['path']
self.conn = sqlite3.connect(self.db_path)
self.create_tables()
def create_tables(self):
"""创建数据表"""
cursor = self.conn.cursor()
# 创建期货合约信息表
cursor.execute('''
CREATE TABLE IF NOT EXISTS futures_info (
symbol TEXT PRIMARY KEY,
name TEXT,
exchange TEXT,
contract_multiplier REAL,
margin_ratio REAL,
min_price_move REAL,
list_date TEXT,
delist_date TEXT,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
''')
# 创建日线数据表
cursor.execute('''
CREATE TABLE IF NOT EXISTS daily_data (
id INTEGER PRIMARY KEY AUTOINCREMENT,
symbol TEXT,
trade_date TEXT,
open REAL,
high REAL,
low REAL,
close REAL,
volume INTEGER,
open_interest REAL,
turnover REAL,
settlement REAL,
pre_settlement REAL,
change REAL,
change_rate REAL,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(symbol, trade_date)
)
''')
# 创建分钟线数据表
cursor.execute('''
CREATE TABLE IF NOT EXISTS minute_data (
id INTEGER PRIMARY KEY AUTOINCREMENT,
symbol TEXT,
datetime TEXT,
open REAL,
high REAL,
low REAL,
close REAL,
volume INTEGER,
open_interest REAL,
period TEXT,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(symbol, datetime, period)
)
''')
self.conn.commit()
self.logger.info("数据库表创建完成")
def fetch_futures_list(self, exchange=None):
"""获取期货合约列表"""
try:
if self.config['data_sources']['preferred'] == 'akshare':
futures_list = ak.futures_zh_spot()
# 数据处理和存储
futures_list.to_sql('futures_info', self.conn, if_exists='replace', index=False)
self.logger.info(f"获取期货列表成功,共{len(futures_list)}个合约")
return futures_list
else:
# 其他数据源实现
pass
except Exception as e:
self.logger.error(f"获取期货列表失败: {str(e)}")
return self.fetch_futures_list_backup(exchange)
def fetch_daily_data(self, symbol, start_date, end_date):
"""获取日线数据"""
try:
if self.config['data_sources']['preferred'] == 'akshare':
df = ak.futures_zh_daily(symbol=symbol, start_date=start_date, end_date=end_date)
df['symbol'] = symbol
df.to_sql('daily_data', self.conn, if_exists='append', index=False)
self.logger.info(f"获取{symbol}日线数据成功,共{len(df)}条记录")
return df
else:
# 其他数据源实现
pass
except Exception as e:
self.logger.error(f"获取{symbol}日线数据失败: {str(e)}")
return self.fetch_daily_data_backup(symbol, start_date, end_date)
def fetch_realtime_data(self, symbols):
"""获取实时行情数据"""
realtime_data = {}
for symbol in symbols:
try:
# 实现实时数据获取逻辑
# 这里使用模拟数据
realtime_data[symbol] = {
'datetime': datetime.now(),
'last_price': np.random.uniform(1000, 5000),
'volume': np.random.randint(100, 10000),
'open_interest': np.random.uniform(1000, 50000),
'bid_price': np.random.uniform(1000, 5000),
'ask_price': np.random.uniform(1000, 5000),
'bid_volume': np.random.randint(1, 100),
'ask_volume': np.random.randint(1, 100)
}
except Exception as e:
self.logger.error(f"获取{symbol}实时数据失败: {str(e)}")
return realtime_data
def fetch_daily_data_backup(self, symbol, start_date, end_date):
"""备用数据源获取日线数据"""
# 实现备用数据源逻辑
pass
def cleanup(self):
"""清理资源"""
if self.conn:
self.conn.close()
3.2 数据处理类
python
class DataProcessor:
def __init__(self, data_fetcher):
self.data_fetcher = data_fetcher
self.logger = logging.getLogger(__name__)
def calculate_technical_indicators(self, df, symbol):
"""计算技术指标"""
try:
# 确保数据按时间排序
df = df.sort_values('trade_date')
# 移动平均线
df['ma5'] = df['close'].rolling(window=5).mean()
df['ma10'] = df['close'].rolling(window=10).mean()
df['ma20'] = df['close'].rolling(window=20).mean()
df['ma60'] = df['close'].rolling(window=60).mean()
# 指数移动平均线
df['ema12'] = df['close'].ewm(span=12).mean()
df['ema26'] = df['close'].ewm(span=26).mean()
df['macd'] = df['ema12'] - df['ema26']
df['macd_signal'] = df['macd'].ewm(span=9).mean()
df['macd_hist'] = df['macd'] - df['macd_signal']
# 相对强弱指数
delta = df['close'].diff()
gain = (delta.where(delta > 0, 0)).rolling(window=14).mean()
loss = (-delta.where(delta < 0, 0)).rolling(window=14).mean()
rs = gain / loss
df['rsi'] = 100 - (100 / (1 + rs))
# 布林带
df['bb_middle'] = df['close'].rolling(window=20).mean()
bb_std = df['close'].rolling(window=20).std()
df['bb_upper'] = df['bb_middle'] + 2 * bb_std
df['bb_lower'] = df['bb_middle'] - 2 * bb_std
# 平均真实范围
high_low = df['high'] - df['low']
high_close = np.abs(df['high'] - df['close'].shift())
low_close = np.abs(df['low'] - df['close'].shift())
ranges = pd.concat([high_low, high_close, low_close], axis=1)
true_range = ranges.max(axis=1)
df['atr'] = true_range.rolling(window=14).mean()
# 动量指标
df['momentum'] = df['close'] - df['close'].shift(4)
self.logger.info(f"技术指标计算完成: {symbol}")
return df
except Exception as e:
self.logger.error(f"计算技术指标失败: {str(e)}")
return df
def detect_patterns(self, df, symbol):
"""检测价格形态"""
patterns = {}
# 检测支撑阻力位
patterns['support_resistance'] = self.find_support_resistance(df)
# 检测趋势
patterns['trend'] = self.detect_trend(df)
# 检测价格形态(头肩顶、双底等)
patterns['price_patterns'] = self.detect_price_patterns(df)
return patterns
def find_support_resistance(self, df, window=20):
"""寻找支撑阻力位"""
# 实现支撑阻力位检测逻辑
support_levels = []
resistance_levels = []
# 简化实现:使用近期高点和低点
for i in range(window, len(df) - window):
window_high = df['high'].iloc[i-window:i+window].max()
window_low = df['low'].iloc[i-window:i+window].min()
if df['high'].iloc[i] == window_high:
resistance_levels.append((df.index[i], df['high'].iloc[i]))
elif df['low'].iloc[i] == window_low:
support_levels.append((df.index[i], df['low'].iloc[i]))
return {
'support': support_levels[-5:], # 返回最近5个支撑位
'resistance': resistance_levels[-5:] # 返回最近5个阻力位
}
def detect_trend(self, df):
"""检测趋势"""
# 使用移动平均线判断趋势
if len(df) < 20:
return "震荡"
current_close = df['close'].iloc[-1]
ma20 = df['ma20'].iloc[-1]
ma60 = df['ma60'].iloc[-1]
if current_close > ma20 > ma60:
return "强势上涨"
elif current_close > ma20 and ma20 > ma60:
return "上涨"
elif ma60 > ma20 > current_close:
return "强势下跌"
elif ma60 > ma20 and ma20 > current_close:
return "下跌"
else:
return "震荡"
def detect_price_patterns(self, df):
"""检测价格形态"""
# 实现价格形态检测逻辑
patterns = []
# 这里可以添加头肩顶、双底、三角形等形态检测
return patterns
4. 策略模块实现
4.1 策略基类
python
from abc import ABC, abstractmethod
import talib
class TradingStrategy(ABC):
def __init__(self, name, params):
self.name = name
self.params = params
self.logger = logging.getLogger(__name__)
self.positions = {}
self.signals = {}
@abstractmethod
def generate_signals(self, data):
"""生成交易信号"""
pass
@abstractmethod
def calculate_position_size(self, signal, account_info):
"""计算仓位大小"""
pass
def update_params(self, new_params):
"""更新策略参数"""
self.params.update(new_params)
self.logger.info(f"策略参数已更新: {new_params}")
def backtest(self, historical_data, initial_capital=1000000):
"""策略回测"""
# 实现回测逻辑
pass
4.2 均线交叉策略
python
class MovingAverageCrossoverStrategy(TradingStrategy):
def __init__(self, params=None):
if params is None:
params = {
'fast_ma_period': 5,
'slow_ma_period': 20,
'stop_loss_pct': 0.02,
'take_profit_pct': 0.04,
'trailing_stop_pct': 0.01
}
super().__init__("Moving Average Crossover", params)
def generate_signals(self, data):
"""生成均线交叉信号"""
signals = {}
for symbol, df in data.items():
if len(df) < self.params['slow_ma_period']:
continue
# 计算移动平均线
fast_ma = df['close'].rolling(window=self.params['fast_ma_period']).mean()
slow_ma = df['close'].rolling(window=self.params['slow_ma_period']).mean()
current_fast_ma = fast_ma.iloc[-1]
current_slow_ma = slow_ma.iloc[-1]
prev_fast_ma = fast_ma.iloc[-2]
prev_slow_ma = slow_ma.iloc[-2]
# 生成信号
signal = {
'symbol': symbol,
'timestamp': df.index[-1],
'price': df['close'].iloc[-1],
'action': 'hold',
'strength': 0,
'stop_loss': None,
'take_profit': None
}
# 金叉:快线上穿慢线
if prev_fast_ma <= prev_slow_ma and current_fast_ma > current_slow_ma:
signal['action'] = 'buy'
signal['strength'] = (current_fast_ma - current_slow_ma) / current_slow_ma
# 设置止损止盈
signal['stop_loss'] = signal['price'] * (1 - self.params['stop_loss_pct'])
signal['take_profit'] = signal['price'] * (1 + self.params['take_profit_pct'])
# 死叉:快线下穿慢线
elif prev_fast_ma >= prev_slow_ma and current_fast_ma < current_slow_ma:
signal['action'] = 'sell'
signal['strength'] = (current_slow_ma - current_fast_ma) / current_slow_ma
# 设置止损止盈
signal['stop_loss'] = signal['price'] * (1 + self.params['stop_loss_pct'])
signal['take_profit'] = signal['price'] * (1 - self.params['take_profit_pct'])
signals[symbol] = signal
self.signals = signals
return signals
def calculate_position_size(self, signal, account_info):
"""基于风险管理的仓位计算"""
if signal['action'] == 'hold':
return 0
# 计算风险金额(账户资金的2%)
risk_amount = account_info['equity'] * 0.02
# 计算每点价值(需要根据具体合约调整)
point_value = 10 # 假设每点价值10元
# 计算止损点数
if signal['action'] == 'buy':
stop_loss_points = (signal['price'] - signal['stop_loss']) / point_value
else:
stop_loss_points = (signal['stop_loss'] - signal['price']) / point_value
# 避免除零错误
if stop_loss_points <= 0:
return 0
# 计算合约数量
position_size = risk_amount / (stop_loss_points * point_value)
# 考虑最大仓位限制
max_position = account_info['equity'] * 0.1 / signal['price'] # 单品种不超过10%
position_size = min(position_size, max_position)
return int(position_size)
4.3 动量策略
python
class MomentumStrategy(TradingStrategy):
def __init__(self, params=None):
if params is None:
params = {
'rsi_period': 14,
'rsi_overbought': 70,
'rsi_oversold': 30,
'macd_fast': 12,
'macd_slow': 26,
'macd_signal': 9,
'stop_loss_pct': 0.015,
'take_profit_pct': 0.03
}
super().__init__("Momentum Strategy", params)
def generate_signals(self, data):
"""生成动量信号"""
signals = {}
for symbol, df in data.items():
if len(df) < max(self.params['rsi_period'], self.params['macd_slow'] + self.params['macd_signal']):
continue
# 计算技术指标
rsi = self.calculate_rsi(df['close'], self.params['rsi_period'])
macd, macd_signal, macd_hist = self.calculate_macd(
df['close'],
self.params['macd_fast'],
self.params['macd_slow'],
self.params['macd_signal']
)
current_rsi = rsi.iloc[-1]
current_macd = macd.iloc[-1]
current_macd_signal = macd_signal.iloc[-1]
prev_macd = macd.iloc[-2]
prev_macd_signal = macd_signal.iloc[-2]
signal = {
'symbol': symbol,
'timestamp': df.index[-1],
'price': df['close'].iloc[-1],
'action': 'hold',
'strength': 0,
'rsi': current_rsi,
'macd': current_macd,
'macd_hist': macd_hist.iloc[-1],
'stop_loss': None,
'take_profit': None
}
# 生成买入信号:RSI超卖或MACD金叉
buy_condition = (
(current_rsi < self.params['rsi_oversold']) or
(prev_macd <= prev_macd_signal and current_macd > current_macd_signal)
)
# 生成卖出信号:RSI超买或MACD死叉
sell_condition = (
(current_rsi > self.params['rsi_overbought']) or
(prev_macd >= prev_macd_signal and current_macd < current_macd_signal)
)
if buy_condition:
signal['action'] = 'buy'
signal['strength'] = self.calculate_signal_strength(signal, 'buy')
signal['stop_loss'] = signal['price'] * (1 - self.params['stop_loss_pct'])
signal['take_profit'] = signal['price'] * (1 + self.params['take_profit_pct'])
elif sell_condition:
signal['action'] = 'sell'
signal['strength'] = self.calculate_signal_strength(signal, 'sell')
signal['stop_loss'] = signal['price'] * (1 + self.params['stop_loss_pct'])
signal['take_profit'] = signal['price'] * (1 - self.params['take_profit_pct'])
signals[symbol] = signal
self.signals = signals
return signals
def calculate_rsi(self, prices, period):
"""计算RSI指标"""
delta = prices.diff()
gain = (delta.where(delta > 0, 0)).rolling(window=period).mean()
loss = (-delta.where(delta < 0, 0)).rolling(window=period).mean()
rs = gain / loss
rsi = 100 - (100 / (1 + rs))
return rsi
def calculate_macd(self, prices, fast_period, slow_period, signal_period):
"""计算MACD指标"""
ema_fast = prices.ewm(span=fast_period).mean()
ema_slow = prices.ewm(span=slow_period).mean()
macd = ema_fast - ema_slow
macd_signal = macd.ewm(span=signal_period).mean()
macd_hist = macd - macd_signal
return macd, macd_signal, macd_hist
def calculate_signal_strength(self, signal, action):
"""计算信号强度"""
strength = 0
if action == 'buy':
# RSI越低,买入信号越强
rsi_strength = max(0, (self.params['rsi_oversold'] - signal['rsi']) / self.params['rsi_oversold'])
# MACD柱状线越负,买入信号越强
macd_strength = max(0, -signal['macd_hist'] / (signal['price'] * 0.01)) # 标准化
strength = (rsi_strength * 0.6 + macd_strength * 0.4) * 100
else: # sell
# RSI越高,卖出信号越强
rsi_strength = max(0, (signal['rsi'] - self.params['rsi_overbought']) / (100 - self.params['rsi_overbought']))
# MACD柱状线越正,卖出信号越强
macd_strength = max(0, signal['macd_hist'] / (signal['price'] * 0.01)) # 标准化
strength = (rsi_strength * 0.6 + macd_strength * 0.4) * 100
return min(strength, 100) # 限制在0-100范围内
def calculate_position_size(self, signal, account_info):
"""基于波动率的仓位计算"""
if signal['action'] == 'hold':
return 0
# 计算ATR(平均真实范围)
# 这里简化处理,实际需要计算ATR
atr = signal['price'] * 0.01 # 假设ATR为价格的1%
# 计算风险金额(账户资金的1.5%)
risk_amount = account_info['equity'] * 0.015
# 计算合约数量
position_size = risk_amount / (atr * 1.5) # 1.5倍ATR作为止损
# 考虑最大仓位限制
max_position = account_info['equity'] * 0.08 / signal['price'] # 单品种不超过8%
position_size = min(position_size, max_position)
return int(position_size)
4.4 策略组合管理
python
class StrategyManager:
def __init__(self, strategies, weights=None):
self.strategies = strategies
self.weights = weights or [1/len(strategies)] * len(strategies)
self.logger = logging.getLogger(__name__)
self.combined_signals = {}
def generate_combined_signals(self, data):
"""生成组合信号"""
all_signals = {}
# 收集所有策略的信号
for i, strategy in enumerate(self.strategies):
signals = strategy.generate_signals(data)
for symbol, signal in signals.items():
if symbol not in all_signals:
all_signals[symbol] = []
all_signals[symbol].append({
'strategy': strategy.name,
'signal': signal,
'weight': self.weights[i]
})
# 组合信号
combined_signals = {}
for symbol, signal_list in all_signals.items():
combined_signal = self.combine_signals(signal_list)
combined_signals[symbol] = combined_signal
self.combined_signals = combined_signals
return combined_signals
def combine_signals(self, signal_list):
"""组合多个策略的信号"""
if not signal_list:
return None
# 初始化组合信号
combined = {
'symbol': signal_list[0]['signal']['symbol'],
'timestamp': signal_list[0]['signal']['timestamp'],
'price': signal_list[0]['signal']['price'],
'action': 'hold',
'strength': 0,
'component_signals': [],
'stop_loss': None,
'take_profit': None
}
buy_strength = 0
sell_strength = 0
total_weight = 0
for item in signal_list:
signal = item['signal']
weight = item['weight']
combined['component_signals'].append({
'strategy': item['strategy'],
'action': signal['action'],
'strength': signal['strength']
})
if signal['action'] == 'buy':
buy_strength += signal['strength'] * weight
total_weight += weight
elif signal['action'] == 'sell':
sell_strength += signal['strength'] * weight
total_weight += weight
if total_weight > 0:
if buy_strength > sell_strength:
combined['action'] = 'buy'
combined['strength'] = buy_strength / total_weight
elif sell_strength > buy_strength:
combined['action'] = 'sell'
combined['strength'] = sell_strength / total_weight
# 设置止损止盈(使用加权平均)
stop_loss_sum = 0
take_profit_sum = 0
weight_sum = 0
for item in signal_list:
signal = item['signal']
weight = item['weight']
if signal['stop_loss'] is not None and signal['action'] == combined['action']:
stop_loss_sum += signal['stop_loss'] * weight
take_profit_sum += signal['take_profit'] * weight
weight_sum += weight
if weight_sum > 0:
combined['stop_loss'] = stop_loss_sum / weight_sum
combined['take_profit'] = take_profit_sum / weight_sum
return combined
def update_strategy_weights(self, new_weights):
"""更新策略权重"""
if len(new_weights) != len(self.strategies):
self.logger.error("权重数量与策略数量不匹配")
return False
self.weights = new_weights
self.logger.info(f"策略权重已更新: {new_weights}")
return True
5. 风险控制模块
5.1 风控管理器
python
class RiskManager:
def __init__(self, config):
self.config = config
self.logger = logging.getLogger(__name__)
self.violations = []
def check_position_risk(self, positions, account_info):
"""检查持仓风险"""
risks = {
'max_position_risk': self.check_max_position_risk(positions, account_info),
'sector_exposure': self.check_sector_exposure(positions, account_info),
'liquidity_risk': self.check_liquidity_risk(positions),
'leverage_risk': self.check_leverage_risk(positions, account_info)
}
# 检查是否有风险违规
has_violation = any(risks.values())
if has_violation:
self.logger.warning("发现风险违规,需要调整仓位")
self.violations.append({
'timestamp': datetime.now(),
'risks': risks
})
return risks
def check_max_position_risk(self, positions, account_info):
"""检查单品种最大仓位风险"""
violation = False
for symbol, position in positions.items():
position_value = position['quantity'] * position['current_price']
position_ratio = position_value / account_info['equity']
if position_ratio > self.config['max_position_ratio']:
self.logger.warning(
f"品种{symbol}仓位超过限制: {position_ratio:.2%} > "
f"{self.config['max_position_ratio']:.2%}"
)
violation = True
return violation
def check_sector_exposure(self, positions, account_info):
"""检查行业暴露风险"""
# 这里需要根据期货品种的行业分类进行检查
# 简化实现:假设所有品种属于同一行业
total_exposure = sum(
pos['quantity'] * pos['current_price']
for pos in positions.values()
)
exposure_ratio = total_exposure / account_info['equity']
violation = exposure_ratio > self.config['max_sector_exposure']
if violation:
self.logger.warning(
f"行业暴露超过限制: {exposure_ratio:.2%} > "
f"{self.config['max_sector_exposure']:.2%}"
)
return violation
def check_liquidity_risk(self, positions):
"""检查流动性风险"""
# 实现流动性检查逻辑
# 这里简化处理
return False
def check_leverage_risk(self, positions, account_info):
"""检查杠杆风险"""
total_position_value = sum(
pos['quantity'] * pos['current_price']
for pos in positions.values()
)
leverage = total_position_value / account_info['equity']
violation = leverage > self.config['max_leverage']
if violation:
self.logger.warning(
f"杠杆超过限制: {leverage:.2f} > {self.config['max_leverage']}"
)
return violation
def generate_risk_adjustment(self, signals, positions, account_info):
"""生成风险调整建议"""
adjustments = []
# 检查现有持仓的风险
risk_result = self.check_position_risk(positions, account_info)
# 如果有风险违规,生成减仓建议
if any(risk_result.values()):
for symbol, position in positions.items():
position_value = position['quantity'] * position['current_price']
position_ratio = position_value / account_info['equity']
if position_ratio > self.config['max_position_ratio']:
target_value = account_info['equity'] * self.config['max_position_ratio']
reduce_quantity = position['quantity'] - (target_value / position['current_price'])
adjustments.append({
'symbol': symbol,
'action': 'reduce',
'quantity': max(0, int(reduce_quantity)),
'reason': '超过单品种仓位限制'
})
# 对新信号进行风险检查
for symbol, signal in signals.items():
if signal['action'] == 'hold':
continue
# 计算拟建仓价值
proposed_size = signal.get('proposed_quantity', 0)
proposed_value = proposed_size * signal['price']
proposed_ratio = proposed_value / account_info['equity']
# 检查是否超过单品种限制
if proposed_ratio > self.config['max_position_ratio']:
max_value = account_info['equity'] * self.config['max_position_ratio']
max_quantity = int(max_value / signal['price'])
adjustments.append({
'symbol': symbol,
'action': 'adjust',
'original_quantity': proposed_size,
'adjusted_quantity': max_quantity,
'reason': '超过单品种仓位限制'
})
# 检查是否会导致行业暴露超标
current_exposure = sum(
pos['quantity'] * pos['current_price']
for pos in positions.values()
)
new_exposure = current_exposure + proposed_value
if new_exposure / account_info['equity'] > self.config['max_sector_exposure']:
max_additional = (account_info['equity'] * self.config['max_sector_exposure'] - current_exposure)
max_quantity = int(max_additional / signal['price'])
adjustments.append({
'symbol': symbol,
'action': 'adjust',
'original_quantity': proposed_size,
'adjusted_quantity': min(proposed_size, max_quantity),
'reason': '超过行业暴露限制'
})
return adjustments
5.2 资金管理类
python
class MoneyManager:
def __init__(self, config):
self.config = config
self.logger = logging.getLogger(__name__)
self.performance_history = []
def calculate_position_size(self, signal, account_info, risk_per_trade=0.02):
"""基于风险的仓位计算"""
if signal['action'] == 'hold':
return 0
# 计算风险金额
risk_amount = account_info['equity'] * risk_per_trade
# 计算止损距离
if signal['stop_loss'] is None:
# 如果没有设置止损,使用默认百分比
stop_loss_pct = self.config['default_stop_loss_pct']
stop_loss_distance = signal['price'] * stop_loss_pct
else:
stop_loss_distance = abs(signal['price'] - signal['stop_loss'])
# 避免除零错误
if stop_loss_distance <= 0:
return 0
# 计算每点价值(需要根据具体合约调整)
point_value = self.get_point_value(signal['symbol'])
# 计算合约数量
position_size = risk_amount / (stop_loss_distance * point_value)
# 考虑最大仓位限制
max_position = account_info['equity'] * self.config['max_position_ratio'] / signal['price']
position_size = min(position_size, max_position)
return int(position_size)
def get_point_value(self, symbol):
"""获取每点价值"""
# 这里需要根据具体期货合约设置每点价值
# 简化实现:根据合约代码判断
if 'IF' in symbol: # 股指期货
return 300
elif 'IC' in symbol:
return 200
elif 'IH' in symbol:
return 300
elif 'AU' in symbol: # 黄金
return 1000
elif 'AG' in symbol: # 白银
return 15
else: # 默认
return 10
def update_account_info(self, account_info, trades, market_data):
"""更新账户信息"""
# 计算持仓市值
positions_value = 0
floating_pnl = 0
for symbol, position in account_info['positions'].items():
if symbol in market_data:
current_price = market_data[symbol]['last_price']
position_value = position['quantity'] * current_price
positions_value += position_value
# 计算浮动盈亏
cost = position['quantity'] * position['avg_cost']
floating_pnl += position_value - cost
# 更新账户信息
account_info['positions_value'] = positions_value
account_info['floating_pnl'] = floating_pnl
account_info['equity'] = account_info['cash'] + positions_value
account_info['update_time'] = datetime.now()
return account_info
def record_performance(self, account_info, timestamp):
"""记录绩效数据"""
performance = {
'timestamp': timestamp,
'equity': account_info['equity'],
'cash': account_info['cash'],
'positions_value': account_info['positions_value'],
'floating_pnl': account_info['floating_pnl'],
'drawdown': self.calculate_drawdown(account_info['equity'])
}
self.performance_history.append(performance)
return performance
def calculate_drawdown(self, current_equity):
"""计算回撤"""
if not self.performance_history:
return 0
peak_equity = max([p['equity'] for p in self.performance_history])
drawdown = (peak_equity - current_equity) / peak_equity if peak_equity > 0 else 0
return drawdown
6. 订单执行模块
6.1 订单管理器
python
class OrderManager:
def __init__(self, broker_api, config):
self.broker_api = broker_api
self.config = config
self.logger = logging.getLogger(__name__)
self.order_history = []
self.pending_orders = []
def create_order(self, symbol, action, quantity, price=None, order_type='limit',
stop_loss=None, take_profit=None, validity='day'):
"""创建订单"""
order = {
'order_id': self.generate_order_id(),
'symbol': symbol,
'action': action,
'quantity': quantity,
'order_type': order_type,
'price': price,
'stop_loss': stop_loss,
'take_profit': take_profit,
'validity': validity,
'status': 'pending',
'create_time': datetime.now(),
'update_time': datetime.now()
}
self.pending_orders.append(order)
self.logger.info(f"创建订单: {order}")
return order
def execute_orders(self, market_data):
"""执行挂单"""
executed_orders = []
for order in self.pending_orders[:]:
if self.check_order_conditions(order, market_data):
# 执行订单
result = self.execute_order(order, market_data)
if result['status'] == 'filled':
executed_orders.append(order)
self.pending_orders.remove(order)
self.order_history.append(order)
return executed_orders
def check_order_conditions(self, order, market_data):
"""检查订单执行条件"""
symbol = order['symbol']
if symbol not in market_data:
return False
current_price = market_data[symbol]['last_price']
if order['order_type'] == 'market':
return True
elif order['order_type'] == 'limit':
if order['action'] == 'buy':
return current_price <= order['price']
else: # sell
return current_price >= order['price']
elif order['order_type'] == 'stop':
if order['action'] == 'buy':
return current_price >= order['price']
else: # sell
return current_price <= order['price']
return False
def execute_order(self, order, market_data):
"""执行单个订单"""
symbol = order['symbol']
current_price = market_data[symbol]['last_price']
# 模拟执行
execution_price = current_price
if order['order_type'] == 'limit' and order['price'] is not None:
execution_price = order['price']
order['status'] = 'filled'
order['execution_price'] = execution_price
order['execution_time'] = datetime.now()
order['update_time'] = datetime.now()
self.logger.info(f"订单执行: {order['order_id']} {order['action']} {order['quantity']} "
f"{symbol} @ {execution_price}")
return order
def cancel_order(self, order_id):
"""取消订单"""
for order in self.pending_orders:
if order['order_id'] == order_id:
order['status'] = 'cancelled'
order['update_time'] = datetime.now()
self.pending_orders.remove(order)
self.order_history.append(order)
self.logger.info(f"订单取消: {order_id}")
return True
self.logger.warning(f"订单不存在或已完成: {order_id}")
return False
def generate_order_id(self):
"""生成订单ID"""
timestamp = int(datetime.now().timestamp() * 1000)
random_suffix = np.random.randint(1000, 9999)
return f"ORD{timestamp}{random_suffix}"
def get_order_status(self, order_id):
"""获取订单状态"""
for order in self.pending_orders + self.order_history:
if order['order_id'] == order_id:
return order['status']
return 'not_found'
6.2 经纪商API接口
python
class BrokerAPI:
def __init__(self, config):
self.config = config
self.logger = logging.getLogger(__name__)
self.connected = False
def connect(self):
"""连接经纪商API"""
try:
# 这里实现实际的API连接逻辑
# 模拟连接过程
time.sleep(1)
self.connected = True
self.logger.info("经纪商API连接成功")
return True
except Exception as e:
self.logger.error(f"经纪商API连接失败: {str(e)}")
return False
def disconnect(self):
"""断开连接"""
self.connected = False
self.logger.info("经纪商API已断开")
def get_account_info(self):
"""获取账户信息"""
if not self.connected:
self.logger.warning("API未连接,无法获取账户信息")
return None
# 模拟账户信息
account_info = {
'account_id': self.config['account_id'],
'equity': np.random.uniform(800000, 1200000),
'cash': np.random.uniform(500000, 800000),
'positions_value': np.random.uniform(200000, 400000),
'floating_pnl': np.random.uniform(-50000, 50000),
'update_time': datetime.now()
}
return account_info
def get_positions(self):
"""获取持仓信息"""
if not self.connected:
self.logger.warning("API未连接,无法获取持仓信息")
return {}
# 模拟持仓数据
symbols = ['IF2401', 'IC2401', 'AU2402', 'AG2403']
positions = {}
for symbol in symbols:
if np.random.random() > 0.7: # 30%概率有持仓
quantity = np.random.randint(1, 10)
avg_cost = np.random.uniform(3000, 6000)
positions[symbol] = {
'symbol': symbol,
'quantity': quantity,
'avg_cost': avg_cost,
'current_price': avg_cost * np.random.uniform(0.9, 1.1)
}
return positions
def place_order(self, symbol, action, quantity, price=None, order_type='limit'):
"""下达订单"""
if not self.connected:
self.logger.warning("API未连接,无法下达订单")
return None
# 模拟下单
order_id = f"BROKER{int(time.time() * 1000)}{np.random.randint(1000, 9999)}"
order = {
'order_id': order_id,
'symbol': symbol,
'action': action,
'quantity': quantity,
'order_type': order_type,
'price': price,
'status': 'pending',
'place_time': datetime.now()
}
self.logger.info(f"经纪商下单: {order}")
return order
def cancel_order(self, order_id):
"""取消订单"""
if not self.connected:
self.logger.warning("API未连接,无法取消订单")
return False
self.logger.info(f"经纪商取消订单: {order_id}")
return True
def get_market_data(self, symbols):
"""获取市场数据"""
if not self.connected:
self.logger.warning("API未连接,无法获取市场数据")
return {}
market_data = {}
for symbol in symbols:
market_data[symbol] = {
'last_price': np.random.uniform(3000, 6000),
'volume': np.random.randint(1000, 10000),
'open_interest': np.random.uniform(10000, 50000),
'bid_price': np.random.uniform(3000, 6000),
'ask_price': np.random.uniform(3000, 6000),
'bid_volume': np.random.randint(1, 100),
'ask_volume': np.random.randint(1, 100),
'timestamp': datetime.now()
}
return market_data
7. 监控与日志模块
7.1 系统监控器
python
class SystemMonitor:
def __init__(self, config):
self.config = config
self.logger = logging.getLogger(__name__)
self.metrics = {
'system_health': 'normal',
'last_check_time': datetime.now(),
'performance_metrics': {},
'risk_metrics': {}
}
self.alert_history = []
def check_system_health(self, trading_engine):
"""检查系统健康状态"""
current_time = datetime.now()
health_status = 'normal'
issues = []
# 检查数据连接
if not trading_engine.data_fetcher.conn:
issues.append("数据库连接异常")
health_status = 'warning'
# 检查API连接
if not trading_engine.broker_api.connected:
issues.append("经纪商API连接异常")
health_status = 'critical'
# 检查策略运行状态
for strategy in trading_engine.strategy_manager.strategies:
if not hasattr(strategy, 'signals') or not strategy.signals:
issues.append(f"策略{strategy.name}信号生成异常")
health_status = 'warning'
# 检查内存使用
import psutil
memory_usage = psutil.virtual_memory().percent
if memory_usage > 90:
issues.append(f"内存使用率过高: {memory_usage}%")
health_status = 'warning'
# 更新监控指标
self.metrics.update({
'system_health': health_status,
'last_check_time': current_time,
'memory_usage': memory_usage,
'active_issues': issues
})
# 如果有严重问题,发送警报
if health_status == 'critical' and issues:
self.send_alert(f"系统严重异常: {', '.join(issues)}")
return health_status, issues
def monitor_performance(self, account_info, trades):
"""监控交易绩效"""
performance_metrics = {
'total_return': (account_info['equity'] - self.config['initial_capital']) / self.config['initial_capital'],
'daily_return': 0,
'sharpe_ratio': self.calculate_sharpe_ratio(account_info),
'max_drawdown': self.calculate_max_drawdown(account_info),
'win_rate': self.calculate_win_rate(trades),
'profit_factor': self.calculate_profit_factor(trades),
'position_ratio': account_info['positions_value'] / account_info['equity']
}
self.metrics['performance_metrics'] = performance_metrics
return performance_metrics
def calculate_sharpe_ratio(self, account_info):
"""计算夏普比率"""
# 简化实现
return np.random.uniform(0.5, 2.0)
def calculate_max_drawdown(self, account_info):
"""计算最大回撤"""
# 简化实现
return np.random.uniform(0.05, 0.15)
def calculate_win_rate(self, trades):
"""计算胜率"""
if not trades:
return 0
winning_trades = [t for t in trades if t.get('pnl', 0) > 0]
return len(winning_trades) / len(trades)
def calculate_profit_factor(self, trades):
"""计算盈利因子"""
if not trades:
return 0
gross_profit = sum(t.get('pnl', 0) for t in trades if t.get('pnl', 0) > 0)
gross_loss = abs(sum(t.get('pnl', 0) for t in trades if t.get('pnl', 0) < 0))
if gross_loss == 0:
return float('inf')
return gross_profit / gross_loss
def send_alert(self, message, level='critical'):
"""发送警报"""
alert = {
'timestamp': datetime.now(),
'level': level,
'message': message,
'acknowledged': False
}
self.alert_history.append(alert)
self.logger.warning(f"系统警报[{level}]: {message}")
# 这里可以实现邮件、短信等报警方式
if level == 'critical':
self.send_email_alert(message)
def send_email_alert(self, message):
"""发送邮件警报"""
# 实现邮件发送逻辑
pass
def generate_report(self, period='daily'):
"""生成监控报告"""
report = {
'period': period,
'generated_time': datetime.now(),
'system_health': self.metrics['system_health'],
'performance_metrics': self.metrics['performance_metrics'],
'risk_metrics': self.metrics['risk_metrics'],
'recent_alerts': self.alert_history[-10:], # 最近10条警报
'recommendations': self.generate_recommendations()
}
return report
def generate_recommendations(self):
"""生成系统优化建议"""
recommendations = []
if self.metrics['system_health'] != 'normal':
recommendations.append("检查并修复系统异常状态")
if self.metrics['performance_metrics'].get('max_drawdown', 0) > 0.1:
recommendations.append("当前回撤较大,建议降低仓位或调整策略")
if self.metrics['performance_metrics'].get('win_rate', 0) < 0.4:
recommendations.append("胜率较低,建议优化策略参数或更换策略")
return recommendations
7.2 日志配置
python
def setup_logging(log_level=logging.INFO, log_file='trading_system.log'):
"""配置日志系统"""
# 创建日志格式
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
# 创建文件处理器
file_handler = logging.FileHandler(log_file)
file_handler.setFormatter(formatter)
file_handler.setLevel(log_level)
# 创建控制台处理器
console_handler = logging.StreamHandler()
console_handler.setFormatter(formatter)
console_handler.setLevel(log_level)
# 配置根日志记录器
root_logger = logging.getLogger()
root_logger.setLevel(log_level)
root_logger.addHandler(file_handler)
root_logger.addHandler(console_handler)
# 避免第三方库的过多日志
logging.getLogger('urllib3').setLevel(logging.WARNING)
logging.getLogger('requests').setLevel(logging.WARNING)
return root_logger
8. 主交易引擎
python
class TradingEngine:
def __init__(self, config_path="config.json"):
# 加载配置
self.load_config(config_path)
# 设置日志
self.logger = setup_logging(
log_level=getattr(logging, self.config.get('log_level', 'INFO')),
log_file=self.config.get('log_file', 'trading_system.log')
)
# 初始化组件
self.initialize_components()
# 运行状态
self.running = False
self.trading_enabled = self.config.get('trading_enabled', False)
self.logger.info("交易引擎初始化完成")
def load_config(self, config_path):
"""加载配置文件"""
try:
with open(config_path, 'r') as f:
self.config = json.load(f)
except FileNotFoundError:
self.logger.warning("配置文件未找到,使用默认配置")
self.config = {
"log_level": "INFO",
"log_file": "trading_system.log",
"trading_enabled": False,
"risk_management": {
"max_position_ratio": 0.1,
"max_sector_exposure": 0.3,
"max_leverage": 3,
"default_stop_loss_pct": 0.02
},
"data_update_interval": 60,
"trading_symbols": ["IF2401", "IC2401", "AU2402", "AG2403"]
}
def initialize_components(self):
"""初始化所有组件"""
# 数据模块
self.data_fetcher = DataFetcher()
self.data_processor = DataProcessor(self.data_fetcher)
# 经纪商API
self.broker_api = BrokerAPI(self.config.get('broker', {}))
# 订单管理
self.order_manager = OrderManager(self.broker_api, self.config)
# 策略管理
self.strategies = [
MovingAverageCrossoverStrategy(),
MomentumStrategy()
]
self.strategy_manager = StrategyManager(self.strategies)
# 风险管理
self.risk_manager = RiskManager(self.config.get('risk_management', {}))
self.money_manager = MoneyManager(self.config.get('risk_management', {}))
# 系统监控
self.monitor = SystemMonitor(self.config)
# 账户信息
self.account_info = {
'equity': self.config.get('initial_capital', 1000000),
'cash': self.config.get('initial_capital', 1000000),
'positions_value': 0,
'floating_pnl': 0,
'positions': {}
}
# 交易历史
self.trade_history = []
self.logger.info("所有组件初始化完成")
def connect_to_broker(self):
"""连接经纪商API"""
success = self.broker_api.connect()
if success:
# 获取最新的账户信息和持仓
self.update_account_info()
return success
def update_account_info(self):
"""更新账户信息"""
broker_account_info = self.broker_api.get_account_info()
broker_positions = self.broker_api.get_positions()
if broker_account_info:
self.account_info.update(broker_account_info)
if broker_positions:
self.account_info['positions'] = broker_positions
self.logger.info(f"账户信息更新完成: 净值={self.account_info['equity']:.2f}")
def fetch_market_data(self):
"""获取市场数据"""
symbols = self.config.get('trading_symbols', [])
market_data = self.broker_api.get_market_data(symbols)
# 补充历史数据计算技术指标
historical_data = {}
for symbol in symbols:
# 这里应该从数据库获取历史数据
# 简化实现:使用模拟数据
historical_data[symbol] = self.generate_sample_data(symbol)
# 计算技术指标
processed_data = {}
for symbol, df in historical_data.items():
processed_data[symbol] = self.data_processor.calculate_technical_indicators(df, symbol)
return market_data, processed_data
def generate_sample_data(self, symbol, days=100):
"""生成样本数据(用于测试)"""
dates = pd.date_range(end=datetime.now(), periods=days, freq='D')
prices = np.random.normal(5000, 500, days).cumsum() + 4000
df = pd.DataFrame({
'trade_date': dates,
'open': prices * np.random.uniform(0.99, 1.01, days),
'high': prices * np.random.uniform(1.0, 1.02, days),
'low': prices * np.random.uniform(0.98, 1.0, days),
'close': prices,
'volume': np.random.randint(1000, 10000, days),
'open_interest': np.random.uniform(10000, 50000, days)
})
df.set_index('trade_date', inplace=True)
return df
def run_strategies(self, processed_data):
"""运行策略生成信号"""
signals = self.strategy_manager.generate_combined_signals(processed_data)
# 计算建议仓位
for symbol, signal in signals.items():
if signal['action'] != 'hold':
position_size = self.money_manager.calculate_position_size(
signal, self.account_info
)
signal['proposed_quantity'] = position_size
return signals
def apply_risk_management(self, signals):
"""应用风险管理"""
# 检查风险并调整信号
risk_adjustments = self.risk_manager.generate_risk_adjustment(
signals, self.account_info['positions'], self.account_info
)
# 应用调整
for adjustment in risk_adjustments:
symbol = adjustment['symbol']
if symbol in signals:
if adjustment['action'] == 'reduce':
# 生成减仓信号
signals[symbol] = {
'symbol': symbol,
'action': 'sell',
'quantity': adjustment['quantity'],
'price': self.account_info['positions'][symbol]['current_price'],
'reason': adjustment['reason']
}
elif adjustment['action'] == 'adjust':
# 调整建议仓位
signals[symbol]['proposed_quantity'] = adjustment['adjusted_quantity']
signals[symbol]['risk_adjustment'] = adjustment['reason']
return signals
def execute_trades(self, signals, market_data):
"""执行交易"""
executed_orders = []
for symbol, signal in signals.items():
if signal['action'] == 'hold':
continue
# 确定订单数量和价格
quantity = signal.get('proposed_quantity', 0)
if quantity <= 0:
continue
# 确定订单类型和价格
order_type = 'limit'
price = market_data[symbol]['ask_price'] if signal['action'] == 'buy' else market_data[symbol]['bid_price']
# 创建订单
order = self.order_manager.create_order(
symbol=symbol,
action=signal['action'],
quantity=quantity,
price=price,
order_type=order_type,
stop_loss=signal.get('stop_loss'),
take_profit=signal.get('take_profit')
)
# 执行订单
executed = self.order_manager.execute_orders(market_data)
executed_orders.extend(executed)
# 记录交易
for order in executed:
self.record_trade(order)
return executed_orders
def record_trade(self, order):
"""记录交易"""
trade = {
'trade_id': f"TRD{int(time.time() * 1000)}{np.random.randint(1000, 9999)}",
'order_id': order['order_id'],
'symbol': order['symbol'],
'action': order['action'],
'quantity': order['quantity'],
'price': order['execution_price'],
'timestamp': order['execution_time'],
'commission': self.calculate_commission(order),
'slippage': self.calculate_slippage(order)
}
self.trade_history.append(trade)
self.logger.info(f"交易记录: {trade}")
return trade
def calculate_commission(self, order):
"""计算手续费"""
# 简化实现:按固定比例计算
commission_rate = 0.0003 # 万分之三
return order['execution_price'] * order['quantity'] * commission_rate
def calculate_slippage(self, order):
"""计算滑点"""
# 简化实现:按固定比例计算
slippage_rate = 0.0001 # 万分之一
return order['execution_price'] * order['quantity'] * slippage_rate
def run_cycle(self):
"""运行一个交易周期"""
self.logger.info("开始交易周期")
try:
# 1. 更新账户信息
self.update_account_info()
# 2. 获取市场数据
market_data, processed_data = self.fetch_market_data()
# 3. 运行策略生成信号
signals = self.run_strategies(processed_data)
# 4. 应用风险管理
signals = self.apply_risk_management(signals)
# 5. 执行交易
if self.trading_enabled:
executed_orders = self.execute_trades(signals, market_data)
self.logger.info(f"本轮执行 {len(executed_orders)} 个订单")
else:
self.logger.info("交易未启用,仅模拟运行")
# 6. 更新账户信息
self.update_account_info()
# 7. 监控系统状态
system_health, issues = self.monitor.check_system_health(self)
# 8. 记录绩效
self.monitor.monitor_performance(self.account_info, self.trade_history)
# 9. 生成报告
if self.config.get('generate_reports', True):
report = self.monitor.generate_report()
self.logger.info(f"系统报告生成完成: 健康状态={system_health}")
self.logger.info("交易周期完成")
return True
except Exception as e:
self.logger.error(f"交易周期执行失败: {str(e)}")
self.monitor.send_alert(f"交易周期执行失败: {str(e)}", 'critical')
return False
def start(self):
"""启动交易引擎"""
self.logger.info("启动交易引擎")
# 连接经纪商API
if not self.connect_to_broker():
self.logger.error("无法连接经纪商API,系统退出")
return False
self.running = True
# 主循环
while self.running:
try:
cycle_start = time.time()
# 运行交易周期
success = self.run_cycle()
# 计算下次运行时间
cycle_time = time.time() - cycle_start
sleep_time = max(0, self.config.get('data_update_interval', 60) - cycle_time)
if sleep_time > 0:
self.logger.info(f"等待 {sleep_time:.1f} 秒后继续")
time.sleep(sleep_time)
except KeyboardInterrupt:
self.logger.info("用户中断,停止交易引擎")
self.stop()
break
except Exception as e:
self.logger.error(f"交易引擎运行异常: {str(e)}")
self.monitor.send_alert(f"交易引擎运行异常: {str(e)}", 'critical')
time.sleep(60) # 异常后等待1分钟再继续
def stop(self):
"""停止交易引擎"""
self.logger.info("停止交易引擎")
self.running = False
self.broker_api.disconnect()
# 生成最终报告
report = self.monitor.generate_report()
self.logger.info(f"最终报告: 总盈亏={(self.account_info['equity'] - self.config.get('initial_capital', 1000000)):.2f}")
9. 系统部署与运行
9.1 配置文件示例
json
{
"log_level": "INFO",
"log_file": "trading_system.log",
"initial_capital": 1000000,
"trading_enabled": false,
"generate_reports": true,
"data_update_interval": 60,
"trading_symbols": ["IF2401", "IC2401", "AU2402", "AG2403"],
"broker": {
"account_id": "123456789",
"api_key": "your_api_key",
"secret_key": "your_secret_key",
"server_url": "https://api.broker.com"
},
"risk_management": {
"max_position_ratio": 0.1,
"max_sector_exposure": 0.3,
"max_leverage": 3,
"default_stop_loss_pct": 0.02,
"risk_per_trade": 0.02
},
"strategies": {
"moving_average": {
"fast_ma_period": 5,
"slow_ma_period": 20,
"stop_loss_pct": 0.02,
"take_profit_pct": 0.04
},
"momentum": {
"rsi_period": 14,
"rsi_overbought": 70,
"rsi_oversold": 30,
"macd_fast": 12,
"macd_slow": 26,
"macd_signal": 9
}
},
"email_alerts": {
"enabled": true,
"smtp_server": "smtp.gmail.com",
"smtp_port": 587,
"username": "your_email@gmail.com",
"password": "your_password",
"recipients": ["alert@yourcompany.com"]
}
}
9.2 主程序入口
python
def main():
"""主程序入口"""
print("期货自动化交易系统启动中...")
# 创建交易引擎实例
engine = TradingEngine("config.json")
try:
# 启动交易引擎
engine.start()
except Exception as e:
print(f"系统运行异常: {e}")
logging.error(f"系统运行异常: {e}", exc_info=True)
finally:
# 确保资源清理
if hasattr(engine, 'data_fetcher'):
engine.data_fetcher.cleanup()
print("系统已退出")
if __name__ == "__main__":
main()
9.3 系统测试与验证
python
class SystemTester:
def __init__(self, engine):
self.engine = engine
self.logger = logging.getLogger(__name__)
def run_backtest(self, start_date, end_date, initial_capital=1000000):
"""运行回测"""
self.logger.info(f"开始回测: {start_date} 至 {end_date}")
# 获取历史数据
historical_data = self.fetch_historical_data(start_date, end_date)
# 初始化回测账户
backtest_account = {
'equity': initial_capital,
'cash': initial_capital,
'positions_value': 0,
'positions': {},
'history': []
}
# 按时间顺序运行策略
results = []
for timestamp, data_snapshot in historical_data.items():
# 运行策略
signals = self.engine.strategy_manager.generate_combined_signals({timestamp: data_snapshot})
# 执行交易(模拟)
trades = self.execute_backtest_trades(signals, backtest_account, data_snapshot)
# 更新账户
self.update_backtest_account(backtest_account, trades, data_snapshot)
# 记录结果
results.append({
'timestamp': timestamp,
'equity': backtest_account['equity'],
'signals': signals,
'trades': trades
})
# 生成回测报告
report = self.generate_backtest_report(results, initial_capital)
self.logger.info(f"回测完成: 最终净值={backtest_account['equity']:.2f}")
return report
def fetch_historical_data(self, start_date, end_date):
"""获取历史数据"""
# 实现历史数据获取逻辑
historical_data = {}
# 这里应该是实际的数据获取代码
return historical_data
def execute_backtest_trades(self, signals, account, market_data):
"""执行回测交易"""
trades = []
# 实现回测交易逻辑
return trades
def update_backtest_account(self, account, trades, market_data):
"""更新回测账户"""
# 实现账户更新逻辑
pass
def generate_backtest_report(self, results, initial_capital):
"""生成回测报告"""
report = {
'initial_capital': initial_capital,
'final_equity': results[-1]['equity'] if results else initial_capital,
'total_return': (results[-1]['equity'] - initial_capital) / initial_capital if results else 0,
'total_trades': sum(len(r['trades']) for r in results),
'winning_trades': 0,
'losing_trades': 0,
'max_drawdown': self.calculate_max_drawdown([r['equity'] for r in results]),
'sharpe_ratio': self.calculate_sharpe_ratio(results),
'performance_by_period': self.calculate_periodic_returns(results)
}
return report
def calculate_max_drawdown(self, equity_curve):
"""计算最大回撤"""
if not equity_curve:
return 0
peak = equity_curve[0]
max_dd = 0
for equity in equity_curve:
if equity > peak:
peak = equity
dd = (peak - equity) / peak
if dd > max_dd:
max_dd = dd
return max_dd
def calculate_sharpe_ratio(self, results):
"""计算夏普比率"""
# 简化实现
returns = []
for i in range(1, len(results)):
daily_return = (results[i]['equity'] - results[i-1]['equity']) / results[i-1]['equity']
returns.append(daily_return)
if not returns:
return 0
avg_return = np.mean(returns)
std_return = np.std(returns)
if std_return == 0:
return 0
return avg_return / std_return * np.sqrt(252) # 年化夏普比率
def calculate_periodic_returns(self, results):
"""计算周期收益"""
periodic_returns = {
'daily': [],
'weekly': [],
'monthly': []
}
# 实现周期收益计算
return periodic_returns
10. 总结与展望
本系统实现了一个完整的期货自动化交易框架,包含以下主要特点:
10.1 系统特点
- 模块化设计:各功能模块独立,便于维护和扩展
- 多策略支持:支持多种交易策略的组合使用
- 全面风控:包含多层次的风险管理系统
- 实时监控:完整的系统监控和报警机制
- 回测功能:支持历史数据回测和策略优化
10.2 未来改进方向
- 机器学习集成:加入机器学习算法进行信号优化
- 高频交易支持:优化系统性能支持高频交易
- 多市场支持:扩展支持股票、期权等多市场交易
- 云端部署:支持云端部署和分布式运行
- 移动监控:开发移动端监控应用
10.3 风险提示
- 实际交易前必须进行充分回测和模拟交易
- 实时交易需考虑网络延迟和系统稳定性
- 策略参数需要根据市场变化定期优化
- 建议初期使用小资金进行实盘测试
该系统为期货交易提供了一个强大的自动化交易平台,但需要注意的是,任何交易策略都无法保证100%盈利,实际使用时需要根据市场情况不断调整和优化策略参数。
注意:本文档提供的代码为示例代码,实际交易使用前需要进行充分的测试和验证。期货交易具有高风险,请谨慎使用自动化交易系统。