Overall Statistics
Total Trades
3564
Average Win
0.20%
Average Loss
-0.17%
Compounding Annual Return
72.131%
Drawdown
24.200%
Expectancy
0.217
Net Profit
75.243%
Sharpe Ratio
1.356
Probabilistic Sharpe Ratio
65.647%
Loss Rate
45%
Win Rate
55%
Profit-Loss Ratio
1.22
Alpha
0.515
Beta
-0.001
Annual Standard Deviation
0.38
Annual Variance
0.144
Information Ratio
0.953
Tracking Error
0.405
Treynor Ratio
-528.632
Total Fees
$68056.69
import pandas as pd

# Import our custom functions
from StationarityAndZScores import *

# Import the Liquid ETF Universe helper methods
from QuantConnect.Data.UniverseSelection import *

class NadionParticleAntennaArray(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2018, 11, 1)  # Set Start Date
        self.SetCash(1000000)  # Set Strategy Cash

        self.SetBrokerageModel(AlphaStreamsBrokerageModel())
        
        self.SetBenchmark('SPY')
        
        self.SetExecution(ImmediateExecutionModel())

        self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel())

        self.UniverseSettings.Resolution = Resolution.Minute
        self.SetUniverseSelection(LiquidETFUniverse())
        
        self.AddEquity('XLE')
        self.Schedule.On(self.DateRules.EveryDay('XLE'), self.TimeRules.AfterMarketOpen('XLE', 5), self.TransformTestTrade)
    
    def TransformTestTrade(self):
        qb = self
        
        symbols = [x.Symbol for x in qb.ActiveSecurities.Values]
        # Copy and paste from research notebook
        # -----------------------------------------------------------------------------
        # Fetch history and returns
        history = qb.History(symbols, 500, Resolution.Hour)
        returns = history.unstack(level = 1).close.transpose().pct_change().dropna()
        
        # Test for stationarity
        stationarity = TestStationartiy(returns)
        
        # Get z-scores
        z_scores = GetZScores(returns)
        # -----------------------------------------------------------------------------

        insights = []

        # Iterate over symbols
        for symbol, value in stationarity.iteritems():
            # Only emit Insights for those whose returns exhibit stationary behavior
            if value:
                # Get most recent z_score
                z_score = z_scores[symbol].tail(1).values[0]
                if z_score < -1:
                    insights.append(Insight.Price(symbol, timedelta(1), InsightDirection.Up))
                elif z_score > 1:
                    if self.Portfolio[symbol].Invested:
                        insights.append(Insight.Price(symbol, timedelta(1), InsightDirection.Flat))

        self.EmitInsights(insights)
import numpy as np
import pandas as pd
from statsmodels.tsa.stattools import adfuller

def TestStationartiy(returns):
    # Return pandas Series with True/False for each symbol
    return pd.Series([adfuller(values)[1] < 0.05 for columns, values in returns.iteritems()], index = returns.columns)
    
def GetZScores(returns):
    # Return pandas DataFrame containing z-scores
    return returns.subtract(returns.mean()).div(returns.std())