mirror of
https://github.com/xavierchuan/FX-ML-Trading-Engine.git
synced 2026-07-27 18:17:44 +00:00
66 lines
2.7 KiB
Python
66 lines
2.7 KiB
Python
from typing import List, Optional
|
|
import pandas as pd
|
|
from datetime import datetime
|
|
|
|
from .base import Strategy, SignalEvent
|
|
from .base import Position
|
|
from ..data.base import MarketDataEvent
|
|
|
|
class MACrossoverStrategy(Strategy):
|
|
"""
|
|
简单移动平均交叉策略
|
|
快线上穿慢线做多,下穿做空
|
|
"""
|
|
def __init__(self, instrument: str, fast_period: int = 50, slow_period: int = 200, position_size: float = 1.0):
|
|
super().__init__(instrument, position_size)
|
|
self.fast_period = fast_period
|
|
self.slow_period = slow_period
|
|
|
|
async def on_data(self, event: MarketDataEvent) -> Optional[SignalEvent]:
|
|
if self.historical_data is None:
|
|
return None
|
|
# 更新收盘价
|
|
close = event.data.get('close') or event.data.get('mid')
|
|
self.historical_data.loc[event.timestamp] = {
|
|
'open': event.data.get('open', close),
|
|
'high': event.data.get('high', close),
|
|
'low': event.data.get('low', close),
|
|
'close': close
|
|
}
|
|
if len(self.historical_data) < self.slow_period:
|
|
return None
|
|
|
|
fast = self.historical_data['close'].rolling(self.fast_period).mean()
|
|
slow = self.historical_data['close'].rolling(self.slow_period).mean()
|
|
|
|
if fast.iloc[-2] <= slow.iloc[-2] and fast.iloc[-1] > slow.iloc[-1]:
|
|
return SignalEvent(
|
|
instrument=self.instrument,
|
|
timestamp=event.timestamp,
|
|
signal_type="LONG",
|
|
direction="BUY",
|
|
strength=self.position_size
|
|
)
|
|
if fast.iloc[-2] >= slow.iloc[-2] and fast.iloc[-1] < slow.iloc[-1]:
|
|
return SignalEvent(
|
|
instrument=self.instrument,
|
|
timestamp=event.timestamp,
|
|
signal_type="SHORT",
|
|
direction="SELL",
|
|
strength=self.position_size
|
|
)
|
|
return None
|
|
|
|
async def calculate_signals(self, data: pd.DataFrame) -> List[SignalEvent]:
|
|
signals = []
|
|
self.historical_data = data.copy()
|
|
fast = data['close'].rolling(self.fast_period).mean()
|
|
slow = data['close'].rolling(self.slow_period).mean()
|
|
for i in range(self.slow_period, len(data)):
|
|
ts = data.index[i]
|
|
if fast.iloc[i-1] <= slow.iloc[i-1] and fast.iloc[i] > slow.iloc[i]:
|
|
signals.append(SignalEvent(instrument=self.instrument, timestamp=ts, signal_type="LONG", direction="BUY", strength=self.position_size))
|
|
if fast.iloc[i-1] >= slow.iloc[i-1] and fast.iloc[i] < slow.iloc[i]:
|
|
signals.append(SignalEvent(instrument=self.instrument, timestamp=ts, signal_type="SHORT", direction="SELL", strength=self.position_size))
|
|
return signals
|