Overall Statistics
Total Trades
283
Average Win
0.37%
Average Loss
-0.11%
Compounding Annual Return
1.044%
Drawdown
5.000%
Expectancy
0.144
Net Profit
2.454%
Sharpe Ratio
0.294
Probabilistic Sharpe Ratio
9.243%
Loss Rate
73%
Win Rate
27%
Profit-Loss Ratio
3.25
Alpha
0.01
Beta
-0.017
Annual Standard Deviation
0.025
Annual Variance
0.001
Information Ratio
-0.832
Tracking Error
0.203
Treynor Ratio
-0.433
Total Fees
$495.80
Estimated Strategy Capacity
$740000000.00
Lowest Capacity Asset
CL XTN6UA1G9QKH
from AlgorithmImports import *

class USFuturesSecurityMasterDataClassicAlgorithm (QCAlgorithm):
    
    threshold = 0.01 # 1%
    
    def Initialize(self):
        self.SetCash(1000000)
        self.SetStartDate(2019, 2, 1)
        self.SetEndDate(2021, 6, 1)

        # Requesting data
        self.continuous_contract = self.AddFuture(Futures.Energies.CrudeOilWTI,
                                                  dataNormalizationMode = DataNormalizationMode.BackwardsRatio,
                                                  dataMappingMode = DataMappingMode.OpenInterest,
                                                  contractDepthOffset = 0)
        self.symbol = self.continuous_contract.Symbol
                      
        # Historical data
        history = self.History(self.symbol, 500, Resolution.Minute)
        self.Debug(f"We got {len(history)} items from our history request")
        
        self.sma = self.SMA(self.symbol, 10, Resolution.Daily)
        if not history.empty:
            for time, row in history.droplevel(0).loc[self.symbol].iterrows():
                self.sma.Update(IndicatorDataPoint(time, row.close))
        

    def OnData(self, data):
        # Accessing data
        for changed_event in data.SymbolChangedEvents.Values:
            if changed_event.Symbol == self.symbol:
                self.Log(f"SymbolChanged event at {self.Time}: {changed_event}")
                
        mapped_symbol = self.continuous_contract.Mapped

        if not (data.Bars.ContainsKey(self.symbol) and self.sma.IsReady and mapped_symbol):
            return
        
        if data.Bars[self.symbol].Price > self.sma.Current.Value * (1+self.threshold) and not self.Portfolio[mapped_symbol].IsLong:
            self.MarketOrder(mapped_symbol, 1)
        elif data.Bars[self.symbol].Price < self.sma.Current.Value * (1-self.threshold) and not self.Portfolio[mapped_symbol].IsShort:
            self.MarketOrder(mapped_symbol, -1)