Overall Statistics
Total Orders
1168
Average Win
0.17%
Average Loss
-0.60%
Compounding Annual Return
5.914%
Drawdown
30.600%
Expectancy
0.063
Start Equity
100000
End Equity
133297.46
Net Profit
33.297%
Sharpe Ratio
0.089
Sortino Ratio
0.089
Probabilistic Sharpe Ratio
5.146%
Loss Rate
17%
Win Rate
83%
Profit-Loss Ratio
0.28
Alpha
-0.02
Beta
0.423
Annual Standard Deviation
0.121
Annual Variance
0.015
Information Ratio
-0.462
Tracking Error
0.133
Treynor Ratio
0.025
Total Fees
$1691.63
Estimated Strategy Capacity
$2000000.00
Lowest Capacity Asset
GSG TKH7EPK7SRC5
Portfolio Turnover
3.31%
Drawdown Recovery
86
from AlgorithmImports import *


class AssetClassTrendFollowingAlgorithm(QCAlgorithmFramework):

    def initialize(self):
        self.set_start_date(self.end_date - timedelta(5*365))
        self.set_cash(100_000)
        self.settings.automatic_indicator_warm_up = True
        # Add a universe of ETFs.
        symbols = [
            Symbol.create(ticker, SecurityType.EQUITY, Market.USA) 
            for ticker in ["SPY", "EFA", "BND", "VNQ", "GSG"]
        ]
        self.universe_settings.resolution = Resolution.DAILY
        self.set_universe_selection(ManualUniverseSelectionModel(symbols))
        # Add the remaining Framework models.
        self.set_alpha(AssetClassTrendFollowingAlphaModel())
        self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel()) 
        self.set_risk_management(NullRiskManagementModel())
        self.set_execution(ImmediateExecutionModel())


class AssetClassTrendFollowingAlphaModel(AlphaModel):
    '''Alpha model that uses an SMA and security price to create insights'''

    def __init__(self, period=10*21, resolution=Resolution.DAILY):
        '''
        Initializes a new instance of the AssetClassTrendFollowingAlphaModel class
        Args:
            period: The SMA period
            resolution: The data resolution
        '''
        self._period = period
        self._resolution = resolution
        self._securities = []

    def update(self, algorithm, data):       
        return [
            Insight.price(security, timedelta(1, seconds=-1), InsightDirection.UP)
            for security in self._securities
            if security.sma.is_ready and security.price > security.sma.current.value
        ]
            
    def on_securities_changed(self, algorithm, changes):
        for security in changes.added_securities:
            security.sma = algorithm.sma(security, self._period, self._resolution)
            self._securities.append(security)