Overall Statistics
Total Trades
2624
Average Win
0.03%
Average Loss
-0.12%
Compounding Annual Return
5.745%
Drawdown
7.400%
Expectancy
0.038
Net Profit
4.282%
Sharpe Ratio
0.508
Probabilistic Sharpe Ratio
30.088%
Loss Rate
16%
Win Rate
84%
Profit-Loss Ratio
0.24
Alpha
0.041
Beta
0.015
Annual Standard Deviation
0.082
Annual Variance
0.007
Information Ratio
-0.129
Tracking Error
0.157
Treynor Ratio
2.866
Total Fees
$0.00
Estimated Strategy Capacity
$0
Lowest Capacity Asset
XAGUSD 8I
from AlgorithmImports import *

class SMAPairsTrading(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2018, 7, 1)   
        self.SetEndDate(2019, 3, 31)
        self.SetCash(100000)
        
        self.AddCfd('XAUUSD', Resolution.Hour);
        self.AddCfd('XAGUSD', Resolution.Hour);

        self.pair = [ ]
        self.spreadMean = SimpleMovingAverage(500)
        self.spreadStd = StandardDeviation(500)
        
    def OnData(self, data):
        spread = self.pair[1].Price - self.pair[0].Price
        self.spreadMean.Update(self.Time, spread)
        self.spreadStd.Update(self.Time, spread) 
        
        upperthreshold = self.spreadMean.Current.Value + self.spreadStd.Current.Value
        lowerthreshold = self.spreadMean.Current.Value - self.spreadStd.Current.Value

        if spread > upperthreshold:
            self.SetHoldings(self.pair[0].Symbol, 1)
            self.SetHoldings(self.pair[1].Symbol, -1)
        
        if spread < lowerthreshold:
            self.SetHoldings(self.pair[0].Symbol, -1)
            self.SetHoldings(self.pair[1].Symbol, 1)
    
    def OnSecuritiesChanged(self, changes):
        self.pair = [x for x in changes.AddedSecurities]
        
        #1. Call for 500 bars of history data for each symbol in the pair and save to the variable history
        history = self.History([x.Symbol for x in self.pair], 500)
        #2. Unstack the Pandas data frame to reduce it to the history close price
        history = history.close.unstack(level=0)
        #3. Iterate through the history tuple and update the mean and standard deviation with historical data 
        for tuple in history.itertuples():
            self.spreadMean.Update(tuple[0], tuple[2]-tuple[1])
            self.spreadStd.Update(tuple[0], tuple[2]-tuple[1])