Skip to content

turtle_quant_1.strategies.momentum.moving_average_crossover

turtle_quant_1.strategies.momentum.moving_average_crossover

Moving average crossover strategy implementation.

MovingAverageCrossover

MovingAverageCrossover(
    sma_candles: int = 5, lma_candles: int = 180
)

Bases: BaseStrategy

A strategy that uses moving averages to generate buy and sell signals.

Leading / Lagging: Lagging Lag period (in candles): (lma_candles - 1) / 2 - (sma_candles - 1) / 2 Effect: Delay in recognizing that a new trend has begun.

Initialize the moving average crossover strategy.

Parameters:

Name Type Description Default
sma_candles int

The number of candles to use for the short moving average.

5
lma_candles int

The number of candles to use for the long moving average.

180
Source code in src/turtle_quant_1/strategies/momentum/moving_average_crossover.py
def __init__(
    self,
    sma_candles: int = 5,
    lma_candles: int = 180,
):
    """Initialize the moving average crossover strategy.

    Args:
        sma_candles: The number of candles to use for the short moving average.
        lma_candles: The number of candles to use for the long moving average.
    """

    super().__init__()
    self.sma_candles = sma_candles
    self.lma_candles = lma_candles

    if sma_candles >= lma_candles:
        raise ValueError(
            f"Short moving average ({sma_candles}) must be less than long moving average ({lma_candles})."
        )

    if (
        lma_candles
        > convert_units(BACKTESTING_MAX_LOOKBACK_DAYS, "1D", CANDLE_UNIT) * 0.5
    ):
        raise ValueError(
            f"This strategy relies on too many lookback candles ({lma_candles}) for meaningful evaluation to be done. "
            f"Maximum lookback is {BACKTESTING_MAX_LOOKBACK_DAYS} days."
        )

generate_historical_scores

generate_historical_scores(
    data: DataFrame, symbol: str
) -> Series

Generate a historical score array for a symbol based on market data.

NOTE: Assume that the data is sorted by datetime.

Parameters:

Name Type Description Default
data DataFrame

DataFrame with OHLCV data.

required
symbol str

The symbol being analyzed.

required

Returns:

Type Description
Series

Score array with each value between -1.0 and +1.0, indexed by the original data's index.

Source code in src/turtle_quant_1/strategies/momentum/moving_average_crossover.py
def generate_historical_scores(self, data: pd.DataFrame, symbol: str) -> pd.Series:
    """Generate a historical score array for a symbol based on market data.

    NOTE: Assume that the data is sorted by datetime.

    Args:
        data: DataFrame with OHLCV data.
        symbol: The symbol being analyzed.

    Returns:
        Score array with each value between -1.0 and +1.0, indexed by the original data's index.
    """

    self.validate_data(data)

    sma = data["Close"].rolling(self.sma_candles).mean()
    lma = data["Close"].rolling(self.lma_candles).mean()

    scaling_factor = 10.0
    score = (sma - lma) * scaling_factor / data["Close"]
    if np.isnan(score.iloc[-1]):
        raise ValueError("Last score should not be NaN")

    return pd.Series(
        data=score.fillna(0).clip(-1, 1).values,
        index=data.index,
    )

generate_prediction_score

generate_prediction_score(
    data: DataFrame, symbol: str
) -> float

Generate a score for the strategy.

NOTE: Assume that the data is sorted by datetime.

Parameters:

Name Type Description Default
data DataFrame

The data to use for the strategy.

required
symbol str

The symbol to use for the strategy.

required
Source code in src/turtle_quant_1/strategies/momentum/moving_average_crossover.py
def generate_prediction_score(self, data: pd.DataFrame, symbol: str) -> float:
    """Generate a score for the strategy.

    NOTE: Assume that the data is sorted by datetime.

    Args:
        data: The data to use for the strategy.
        symbol: The symbol to use for the strategy.
    """
    return self.generate_historical_scores(
        data.iloc[-(self.lma_candles + 1) :], symbol
    ).iloc[-1]