[docs]classSMACrossoverStrategy(BaseStrategy):""" A Simple Moving Average (SMA) Crossover trading strategy. Generates BUY/SELL signals based on fast SMA crossing above/below slow SMA. """def__init__(self,symbol:str,fast_period:int=10,slow_period:int=50,**kwargs:Any):super().__init__(symbol,**kwargs)iffast_period>=slow_period:raiseValueError("Fast period must be less than slow period")self.fast_period=fast_periodself.slow_period=slow_periodself._closes_history=deque(maxlen=self.slow_period)self._has_position=False
[docs]defon_market_event(self,event:MarketEvent):ifevent.symbol!=self.symbol:returncurrent_close=Decimal(str(event.data["close"]))self._closes_history.append(current_close)iflen(self._closes_history)<self.slow_period:logging.debug(f"Not enough history for {self.symbol} on {event.timestamp.date()}. Need {self.slow_period}, have {len(self._closes_history)}.")returnfast_sma_sum_list=list(self._closes_history)[-self.fast_period:]fast_sma=sum(fast_sma_sum_list,Decimal("0"))/self.fast_periodslow_sma_sum_list=list(self._closes_history)slow_sma=sum(slow_sma_sum_list,Decimal("0"))/self.slow_periodiffast_sma>slow_smaandnotself._has_position:self._put_signal_event(event.timestamp,Signal.BUY)self._has_position=Trueeliffast_sma<slow_smaandself._has_position:self._put_signal_event(event.timestamp,Signal.SELL)self._has_position=Falseelse:pass