Overall Statistics
Total Trades
71
Average Win
2.45%
Average Loss
-0.86%
Compounding Annual Return
1670.083%
Drawdown
10.500%
Expectancy
1.312
Net Profit
45.970%
Sharpe Ratio
15.749
Probabilistic Sharpe Ratio
95.550%
Loss Rate
40%
Win Rate
60%
Profit-Loss Ratio
2.85
Alpha
7.107
Beta
0.356
Annual Standard Deviation
0.469
Annual Variance
0.22
Information Ratio
12.962
Tracking Error
0.51
Treynor Ratio
20.746
Total Fees
$83.03
Estimated Strategy Capacity
$4000.00
Lowest Capacity Asset
SUSHIUSD 2PF
#region imports
from AlgorithmImports import *
#endregion
class Pair_Stoch_Algo(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2022, 9, 20)  # Set Start Date
        self.SetEndDate(2022, 11, 7) #Set End Date
        #self.SetAccountCurrency("USD")
        self.SetCash(500)  # Set Strategy Cash
     
        self.SetBrokerageModel(BrokerageName.FTXUS, AccountType.Cash)
        

        self.symbol = self.AddCrypto("SUSHIUSD", Resolution.Hour, Market.FTXUS).Symbol
        self.symbol_2 = self.AddCrypto("MATICUSD", Resolution.Hour, Market.FTXUS).Symbol

        self.sto = Stochastic(14, 1, 3)
        self.sto_2 = Stochastic(14, 1, 3)

    

        chart = Chart("SUSHIUSD")
        #chart.AddSeries(Series('faststoch', SeriesType.Line, "0"))
        chart.AddSeries(Series('Sushi stochk', SeriesType.Line, "0"))
        chart.AddSeries(Series('Sushi stochd', SeriesType.Line, "0"))
        chart.AddSeries(Series('Sushi stochastic', SeriesType.Line, "0"))
        #chart.AddSeries(Series('Price', SeriesType.Line, "0"))
        
        chart_2 = Chart("MATICUSD")
        chart.AddSeries(Series('Solana stochk', SeriesType.Line, "0"))
        chart.AddSeries(Series('Solana stochd', SeriesType.Line, "0"))
        chart.AddSeries(Series('Solana stochastic', SeriesType.Line, "0"))
        
        self.highestPrice = 0
        self.highestPrice_2 =0
        
        
        self.AddChart(chart)
        self.AddChart(chart_2)


        self.next_trade_time = datetime.min
        self.next_trade_time_2 = datetime.min

        self.entryPrice = 0
        self.entryPrice_2 = 0


        self.entryTicket = None
        self.entryTicket_2 = None

        self.month = 0

    
    def IsRebalanceDue(self, time):


        if time.month == self.month or time.month not in [1, 4, 7, 10]:
            return None
        
        self.month = time.month
        return time

    def OnData(self, data):

        self.PlotIndicator()

    ### Sushi Data Time Frame ###    

        if data.QuoteBars.ContainsKey(self.symbol):
            self.sto.Update(data.QuoteBars[self.symbol])
        if self.sto.IsReady:
            indicator_value = self.sto.Current.Value

    ### Solana Data Time Frame ###

        if data.QuoteBars.ContainsKey(self.symbol_2):
            self.sto_2.Update(data.QuoteBars[self.symbol_2])
        if self.sto_2.IsReady:
            indicator_value = self.sto_2.Current.Value

    ### Sushi Stoch Values ###
        
        #sushi_fast_stoch = self.sto.FastStoch.Current.Value
        sushi_stoch_k = self.sto.StochK.Current.Value
        sushi_stoch_d = self.sto.StochD.Current.Value

    ### Solana Stoch Values ###    
        
        #fast_stoch = self.sto.FastStoch.Current.Value
        solana_stoch_k = self.sto_2.StochK.Current.Value
        solana_stoch_d = self.sto_2.StochD.Current.Value

        

        
        price = self.Securities[self.symbol].Price
        price_2 = self.Securities[self.symbol_2].Price
        
        
    ### Sushi Trade Code ###

        if not self.Portfolio[self.symbol].Invested and not self.Transactions.GetOpenOrders(self.symbol):
            if sushi_stoch_d <= 14 and sushi_stoch_d > 6 and self.Time > self.next_trade_time:
                quantity = self.CalculateOrderQuantity("SUSHIUSD", 0.75)
                self.Log("Sushi order quantity set")
                self.Log("Sushi buy Order @ >> {0}".format(self.Securities["SUSHIUSD"].Price))
                self.Log("Sushi stoch D @ >> {0}".format(self.sto.StochD.Current.Value))
                self.entryTicket = self.MarketOrder("SUSHIUSD", quantity)
                self.entryPrice = price

    ### Solana Trade Code ###

        if not self.Portfolio[self.symbol_2].Invested and not self.Transactions.GetOpenOrders(self.symbol_2):
            if solana_stoch_d <= 18 and solana_stoch_d > 15 and self.Time > self.next_trade_time_2:
                quantity_2 = self.CalculateOrderQuantity("MATICUSD", 0.25)
                self.Log("Solana order quantity set")
                self.Log("Solana buy order @ >> {0}".format(self.Securities["MATICUSD"].Price))
                self.Log("Solana stoch D @ >> {0}".format(self.sto_2.StochD.Current.Value))
                self.entryTicket_2 = self.MarketOrder("MATICUSD", quantity_2)
                self.entryPrice_2 = price_2



    ### Sushi Exit Code ###                

        if self.Portfolio[self.symbol].Invested:
            if sushi_stoch_k >= 85 and sushi_stoch_k < 90:  
                self.Log("Liquidate @ >> {0}".format(self.Securities["SUSHIUSD"].Price))
                self.Log("Stoch @ >> {0}".format(self.sto.StochK.Current.Value))
                self.Liquidate("SUSHIUSD")
                self.next_trade_time = self.Time + timedelta(hours = 5)
        
    ### Solana Exit Code ###

        if self.Portfolio[self.symbol_2].Invested:
            if solana_stoch_k >= 82 and solana_stoch_k < 90:  
                self.Log("Solana liquidate @ >> {0}".format(self.Securities["MATICUSD"].Price))
                self.Log("Solana stoch @ >> {0}".format(self.sto_2.StochK.Current.Value))
                self.Liquidate("MATICUSD")
                self.next_trade_time_2 = self.Time + timedelta(hours = 5)
               
    ### Sushi Stop Loss ###

            if price > self.highestPrice:
                self.highestPrice = price 
            
            if self.Securities["SUSHIUSD"].Price < (self.highestPrice * .7):
                self.Liquidate("SUSHIUSD")
                self.Log("Sushi stop loss triggered")

    ### Solana Stop Loss ###

            if price_2 > self.highestPrice_2:
                self.highestPrice_2 = price_2 
            
            if self.Securities["MATICUSD"].Price < (self.highestPrice_2 * .7):
                self.Liquidate("MATICUSD")
                self.Log("Solana stop loss triggered")
                
        


    def PlotIndicator(self):

    ### Sushi Indicators ### 

       #self.Plot("My Indicators", "faststoch", self.sto.FastStoch.Current.Value)
       self.Plot("SUSHIUSD", "Sushi stochk", self.sto.StochK.Current.Value)
       self.Plot("SUSHIUSD", "Sushi stochd", self.sto.StochD.Current.Value)
       self.Plot("SUSHIUSD", "Sushi Price", self.Securities["SUSHIUSD"].Price)

    ### Solana Indicators ###   

       self.Plot("MATICUSD", "Solana stochk", self.sto_2.StochK.Current.Value)
       self.Plot("MATICUSD", "Solana stochd", self.sto_2.StochD.Current.Value)
       self.Plot("MATICUSD", "Solana Price", self.Securities["MATICUSD"].Price)
        #self.Plot("My Indicators", "RSI", self.rsi.Current.Value)

        
    def OnBrokerageDisconnect(self) -> None:
        self.Debug("Brokerage connection lost")

    def OnBrokerageReconnect(self) -> None:
        self.Debug("Brokerage connection restored")