Created with Highcharts 12.1.2EquityJan 14Jan 28Feb 11Feb 25Mar 11Mar 25Apr 8Apr 22May 6May 20Jun 3Jun 17Jul 1950k1,000k1,050k1,100k-4-2000.51-1012020M05M10M23242526
Overall Statistics
Total Orders
30
Average Win
0.84%
Average Loss
-0.33%
Compounding Annual Return
15.218%
Drawdown
2.900%
Expectancy
1.500
Start Equity
1000000
End Equity
1071785.37
Net Profit
7.179%
Sharpe Ratio
1.21
Sortino Ratio
0.786
Probabilistic Sharpe Ratio
70.491%
Loss Rate
29%
Win Rate
71%
Profit-Loss Ratio
2.50
Alpha
0.04
Beta
0.142
Annual Standard Deviation
0.062
Annual Variance
0.004
Information Ratio
-1.569
Tracking Error
0.109
Treynor Ratio
0.529
Total Fees
$1532.28
Estimated Strategy Capacity
$12000000.00
Lowest Capacity Asset
JNJ R735QTJ8XC9X
Portfolio Turnover
6.71%
from AlgorithmImports import *

class MomentumTrendStrategy(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2019, 1, 1)
        self.SetEndDate(2019, 6, 30)
        self.SetCash(1000000)

        # Add AMD and JNJ (Hour resolution)
        self.symbols = []
        self.symbols.append(self.AddEquity("AMD", Resolution.Hour).Symbol)
        self.symbols.append(self.AddEquity("JNJ", Resolution.Hour).Symbol)

        # Dictionary to hold indicators for each stock
        self.indicators = {}
        for symbol in self.symbols:
            self.indicators[symbol] = {
                "sma50": self.SMA(symbol, 20, Resolution.Hour),
                "sma200": self.SMA(symbol, 70, Resolution.Hour),
                "rsi": self.RSI(symbol, 14, MovingAverageType.Simple, Resolution.Hour),
                "bb": self.BB(symbol, 20, 2, Resolution.Hour)
            }

        # Warm up indicators
        self.SetWarmUp(200)

    def OnData(self, data):
        if self.IsWarmingUp:
            return

        for symbol in self.symbols:
            if symbol not in data:
                continue

            ind = self.indicators[symbol]
            if not all([ind["sma50"].IsReady, ind["sma200"].IsReady, ind["rsi"].IsReady, ind["bb"].IsReady]):
                continue

            price = self.Securities[symbol].Price
            sma50 = ind["sma50"].Current.Value
            sma200 = ind["sma200"].Current.Value
            rsi = ind["rsi"].Current.Value
            bb = ind["bb"]
            upperBB = bb.UpperBand.Current.Value
            middleBB = bb.MiddleBand.Current.Value
            lowerBB = bb.LowerBand.Current.Value

            # Define base position (trend-following component)
            # baseWeight = 0.25 if sma50 > sma200 else -0.25

            # Adjust exposure based on momentum signals
            ShortSignal = sma50 < sma200 and price > upperBB and rsi > 75
            LongSignal = sma50 > sma200 and price < lowerBB and rsi < 25

            targetWeight = 0
            if LongSignal:
                targetWeight = 0.5
            elif ShortSignal:
                targetWeight = -0.5

            # Exit all positions when momentum weakens
            if self.Portfolio[symbol].IsLong and (price > middleBB and rsi > 60):
                self.Liquidate(symbol)  # Close entire long position
                targetWeight = 0  # Optional: Explicitly set weight to zero
                
            elif self.Portfolio[symbol].IsShort and (price < middleBB and rsi < 40):
                self.Liquidate(symbol)  # Close entire short position
                targetWeight = 0  # Optional: Explicitly set weight to zero

            # Only set holdings if not liquidating
            if targetWeight != 0:
                self.SetHoldings(symbol, targetWeight)

            # Debugging output
            self.Debug(f"{self.Time} {symbol.Value}: Price={price:.2f}, SMA50={sma50:.2f}, SMA200={sma200:.2f}, "
                       f"RSI={rsi:.2f}, UpperBB={upperBB:.2f}, MiddleBB={middleBB:.2f}, LowerBB={lowerBB:.2f}, "
                       f"Target Weight={targetWeight:.2f}")