Overall Statistics
Total Trades
1635
Average Win
3.79%
Average Loss
-0.99%
Compounding Annual Return
15.005%
Drawdown
45.200%
Expectancy
0.195
Net Profit
52.269%
Sharpe Ratio
0.494
Probabilistic Sharpe Ratio
12.076%
Loss Rate
75%
Win Rate
25%
Profit-Loss Ratio
3.83
Alpha
-0.09
Beta
0.288
Annual Standard Deviation
0.498
Annual Variance
0.248
Information Ratio
-1.429
Tracking Error
0.644
Treynor Ratio
0.854
Total Fees
$57028.29
Estimated Strategy Capacity
$350000.00
Lowest Capacity Asset
RGTUSD XJ
# This guy is using a strategy for cypto that looks at relative strength out of a basket of cryptos to pick the best ones.
# Could be a good starting point.
# https://www.youtube.com/watch?v=yuZBBX47xK0&list=PLtqRgJ_TIq8Y6YG8G-ETIFW_36mvxMLad&index=14&t=135s

import pandas as pd
from io import StringIO

class JumpingRedOrangeCobra(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2019, 1, 1)  
        self.SetEndDate(2022, 1, 1) 
        self.SetCash(100000)  
        self.SetBrokerageModel(BrokerageName.GDAX, AccountType.Cash)
        self.Settings.FreePortfolioValuePercentage = 0.05 
        self.positionSizeUSD = 5000  
        self.rsiEntryThreshold = 70 
        self.rsiExitThreshold = 60 
        self.minimumVolume = 1000000  
        url = 'https://raw.githubusercontent.com/QuantConnect/Lean/master/Data/symbol-properties/symbol-properties-database.csv'
        content = self.Download(url)
        stringData = StringIO(content)
        df = pd.read_csv(stringData)
        gdax = df[df["market"].str.contains('gdax')]
        gdax = gdax[gdax["symbol"].str.endswith("USD")].reset_index()
        universe = gdax['symbol'].tolist()
        self.pairs = [ Pair(self, ticker, self.minimumVolume) for ticker in universe ]
        self.SetBenchmark("BTCUSD") 
        self.SetWarmup(30, Resolution.Daily) 
        
        
    def OnData(self, data):
        if self.IsWarmingUp: return
        
        
        for pair in self.pairs:
            if not pair.rsi.IsReady: continue
            symbol = pair.symbol
            rsi = pair.rsi.Current.Value
            
            if self.Portfolio[symbol].Invested:
                if not pair.Investable():
                    self.Liquidate(symbol, "Not enough volume") 
                elif rsi < self.rsiExitThreshold:
                    self.Liquidate(symbol, "RSI below threshiold")

            if not pair.Investable(): continue
           
            if rsi > self.rsiEntryThreshold and self.Portfolio.MarginRemaining > self.positionSizeUSD:
                self.Buy(symbol, self.positionSizeUSD / self.Securities[symbol].Price)


class Pair:
    def __init__(self, algorithm, ticker, minimumVolumne):
        self.symbol = algorithm.AddCrypto(ticker, Resolution.Daily, Market.GDAX).Symbol
        self.rsi = algorithm.RSI(self.symbol, 14, MovingAverageType.Simple, Resolution.Daily)
        self.volume = IndicatorExtensions.Times(algorithm.SMA(self.symbol, 30, Resolution.Daily, Field.Volume),
                                                algorithm.SMA(self.symbol, 30, Resolution.Daily, Field.Close))
        self.minimumVolume = minimumVolumne
        
    def Investable(self):
        return (self.volume.Current.Value > self.minimumVolume)