Overall Statistics
Total Trades
89
Average Win
10.88%
Average Loss
-3.24%
Compounding Annual Return
8.681%
Drawdown
56.200%
Expectancy
0.042
Net Profit
10.279%
Sharpe Ratio
0.468
Probabilistic Sharpe Ratio
26.462%
Loss Rate
76%
Win Rate
24%
Profit-Loss Ratio
3.36
Alpha
0.428
Beta
-0.23
Annual Standard Deviation
0.516
Annual Variance
0.266
Information Ratio
-0.469
Tracking Error
1.219
Treynor Ratio
-1.046
Total Fees
$1115.16
import numpy as np
import pandas as pd
from System.Drawing import Color
from QuantConnect.Data.Custom import *
from collections import deque
from QuantConnect.Indicators import *
import decimal as d

class QuantumOptimizedPrism(QCAlgorithm):

    def Initialize(self):
        
        self.Lookback = 175
        #self.SetBrokerageModel(BrokerageName.Alpaca, AccountType.Cash)
        self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin)
        self.SetCash(100000)
        
        #self.symbolList = ["PG", "JNJ", "UNH", "MCK", "CI", "ABC", "NEE", "DUK", "T", "VZ", "VOD"]
        self.symbolList = ["SPXL"]
        #Initialize price change checks and holdings weight
        self.rollingWindow = {}
        self.weights = {}
        self.flashcheck = {}
        #Initialize Exponential Moving Averages
        self.EMAreq = None
        self.EMAshort = None
        self.EMAlong = None
        #Input date information for backtesting
        self.SetStartDate(2019, 6, 27)
        self.SetEndDate(2020, 8, 29)
        self.SetBenchmark("SPXL")
        self.SetWarmUp(self.Lookback)
        
        stockPlot = Chart("Trade Plot")
        stockPlot.AddSeries(Series('Price', SeriesType.Line, '$', Color.Blue))
        #stockPlot.AddSeries(Series('orderBuy', SeriesType.Scatter, '$', Color.Green, ScatterMarkerSymbol.Triangle))
        #stockPlot.AddSeries(Series('orderSell', SeriesType.Scatter, '$', Color.Red, ScatterMarkerSymbol.TriangleDown))
        
        stockPlot = Chart("Diamonds")
        stockPlot.AddSeries(Series('Short>Long', SeriesType.Scatter, '$', Color.Gold, ScatterMarkerSymbol.Diamond))
        stockPlot.AddSeries(Series('Long<Short', SeriesType.Scatter, '$', Color.Purple, ScatterMarkerSymbol.Diamond))
        stockPlot.AddSeries(Series('Above220EMA', SeriesType.Scatter, '$', Color.Green, ScatterMarkerSymbol.Diamond))
        stockPlot.AddSeries(Series('orderBuy', SeriesType.Scatter, '$', Color.Green, ScatterMarkerSymbol.Triangle))
        stockPlot.AddSeries(Series('orderSell', SeriesType.Scatter, '$', Color.Red, ScatterMarkerSymbol.TriangleDown))
        
        self.AddChart(stockPlot)
        
        #Initialize symbols
        for ticker in self.symbolList:
            #self.AddEquity(name, Resolution.Minute)
            self.AddEquity(ticker, Resolution.Hour)
            self.rollingWindow["close_top_{0}".format(ticker)] = deque(maxlen=self.Lookback)
            self.weights[ticker] =  1 / len(self.symbolList)
            self.flashcheck[ticker] = 0
        
            self.EMAreq = self.EMA(ticker, 220, Resolution.Hour);
            self.PlotIndicator('Trade Plot', self.EMAreq);
            
            self.EMAshort = self.EMA(ticker, 13, Resolution.Hour);
            #self.PlotIndicator("My Indicators", self.EMAshort);
            self.PlotIndicator('Trade Plot', self.EMAshort);
            
            self.EMAlong = self.EMA(ticker, 49, Resolution.Hour);
            self.PlotIndicator('Trade Plot', self.EMAlong);
    

    def OnData(self, data):

        profitTargetPercent = 0.075
        stopLossPercent = 0.05
        
        buycrossover = 40 
        self.Plot("Diamonds", "Short>Long", buycrossover)
        sellcrossover = 40
        self.Plot("Diamonds", "Long<Short", sellcrossover)
        #emaclear = 40
        #self.Plot("Diamonds", "Above220EMA", emaclear)
            
        '''Perform preliminary symbol data confirmation'''
        if not all([data.Bars.ContainsKey(symbol) for symbol in self.symbolList]):
            return
        
        '''Algorithm engine'''
        for symbol in self.symbolList:
            self.Plot('Trade Plot', 'Price', data.Bars[symbol].Close)
            sym_price = data[symbol].Price

            self.rollingWindow["close_top_{0}".format(symbol)].appendleft(sym_price)
            
            
            '''Check for algo being warmed up, not being in flash crash, and being above 220 EMA'''
            if not self.IsWarmingUp:
                if not self.EMAlong.IsReady:
                    return  
                if not self.EMAshort.IsReady:
                    return
                if not self.EMAreq.IsReady:
                    return
                
                if self.EMAreq.Current.Value < sym_price:
                    #self.SetHoldings(symbol, 0)
                    #self.Plot("Trade Plot", "Sell", sym_price)
                    emaclear = 43
                    self.Plot("Diamonds", "Above220EMA", emaclear)

                    if self.EMAshort.Current.Value > self.EMAlong.Current.Value and not self.Portfolio[symbol].IsLong:
                        '''If there is a bullish EMA Crossover'''
                        self.SetHoldings(symbol, self.weights[symbol])
                        #self.LimitOrder(symbol, -self.weights[symbol], sym_price * (1 + profitTargetPercent))
                        #self.StopMarketOrder(symbol, -self.weights[symbol], sym_price * (1 - stopLossPercent))
                        buycrossover = 50
                        self.Plot("Diamonds", "Short>Long", buycrossover)

                    elif self.EMAshort.Current.Value < self.EMAlong.Current.Value:
                        '''Liquidate holdings and cancel Open Orders'''
                        #self.Transactions.CancelOpenOrders()
                        self.Liquidate(symbol)
                        sellcrossover = 45
                        self.Plot("Diamonds", "Long<Short", sellcrossover)

                
                elif self.EMAreq.Current.Value > sym_price:
                    if self.EMAshort.Current.Value < self.EMAlong.Current.Value and not self.Portfolio[symbol].IsShort:
                        '''If there is a bullish EMA Crossover'''
                        self.SetHoldings(symbol, -self.weights[symbol])
                        #self.LimitOrder(symbol, self.weights[symbol], sym_price * (1 + profitTargetPercent))
                        #self.StopMarketOrder(symbol, self.weights[symbol], sym_price * (1 - stopLossPercent))
                        buycrossover = 50
                        self.Plot("Diamonds", "Short>Long", buycrossover)

                    elif self.EMAshort.Current.Value > self.EMAlong.Current.Value:
                        '''Liquidate holdings and cancel Open Orders'''
                        #self.Transactions.CancelOpenOrders()
                        self.Liquidate(symbol)
                        sellcrossover = 45
                        self.Plot("Diamonds", "Long<Short", sellcrossover)
                    #self.Transactions.CancelOpenOrders()
                    #self.SetHoldings(symbol, 0)
                        

            
    def OnOrderEvent(self, orderEvent):
        '''Print ordr summary in console'''
        order = self.Transactions.GetOrderById(orderEvent.OrderId)
        self.Debug("{} {}".format(self.Time, orderEvent.ToString()))
        '''Bad way of plotting buy and sell orders'''
        if orderEvent.FillQuantity > 0:
            #self.Plot("Trade Plot", 'orderBuy', orderEvent.FillPrice);
            self.Plot("Diamonds", 'orderBuy', 48);
        elif orderEvent.FillQuantity < 0:
            #self.Plot("Trade Plot", 'orderSell', orderEvent.FillPrice);
            self.Plot("Diamonds", 'orderSell', 47);
        #self.Plot("Trade Plot", 'Order', orderEvent.FillPrice);
        #self.Plot("Diamonds", 'orderBuy', 47);
        #self.Plot("Diamonds", 'orderSell', 47);
        

    def OnEndOfAlgorithm(self):
        self.Log("{} - TotalPortfolioValue: {}".format(self.Time, self.Portfolio.TotalPortfolioValue))
        self.Log("{} - CashBook: {}".format(self.Time, self.Portfolio.CashBook))