Overall Statistics
Total Trades
593
Average Win
1.84%
Average Loss
-0.88%
Compounding Annual Return
207.519%
Drawdown
35.900%
Expectancy
0.241
Net Profit
112.530%
Sharpe Ratio
2.687
Probabilistic Sharpe Ratio
74.970%
Loss Rate
60%
Win Rate
40%
Profit-Loss Ratio
2.10
Alpha
1.469
Beta
0.614
Annual Standard Deviation
0.586
Annual Variance
0.344
Information Ratio
2.484
Tracking Error
0.565
Treynor Ratio
2.566
Total Fees
$9122.33
import decimal as d
import numpy as np

class CryptoTechnical(QCAlgorithm):

    def Initialize(self):
        
        self.Debug('Initializing...')
        self.SetStartDate(2020, 1, 1)  # Set Start Date
        self.SetEndDate(2020, 9, 1)    # Set End Date
        self.fiat = 'EUR'
        self.crypto = 'ETH'
        # Set Strategy Cash (USD)
        self.SetCash(1)
        # Set Strategy Cash (EUR)
        self.SetCash(self.fiat, 6000, 1.1)
        self.SetBrokerageModel(BrokerageName.GDAX, AccountType.Cash)
        self.pair = self.crypto + self.fiat
        self.symbol = self.AddCrypto(self.pair, Resolution.Minute, Market.GDAX).Symbol
        
        #Symbol Data Dictionary:
        self.symbol_data = {}
        
        # Indicator Parameters
        self.ind_params = (26, 12, 9)
        #Create symbol data object for symbol
        self.InitizalizeSymbolData(self.symbol, self.ind_params)
        self.Debug('Initialized.')
        
    def OnData(self, data):
        for key, symbol_data in self.symbol_data.items():
            symbol_data.ComputeStatus()
            if self.Time.minute % 15 == 0 and self.LiveMode:
                inspection = symbol_data.indicator.Signal.Current.Value
                self.Debug('Indicator: '+str(inspection))
                decision = 'Buy' if symbol_data.is_buy else 'Sell'
                self.Debug('Decision:'+str(decision))
           
            fiat_amount = self.Portfolio.CashBook[self.fiat].Amount
            crypto_amount = self.Portfolio.CashBook[self.crypto].Amount
            
            if symbol_data.is_buy == True and self.Portfolio.CashBook[self.fiat].Amount > 100 :
                Price = data[key].Close
                quantity = round((self.Portfolio.CashBook[self.fiat].Amount*0.99)/Price, 3)
                if quantity > 0:
                    self.MarketOrder(key, quantity)
                
            if symbol_data.is_sell == True and self.Portfolio.CashBook[self.crypto].Amount > 0.01 :
                Price = data[key].Close
                quantity = round(self.Portfolio.CashBook[self.crypto].Amount*0.99, 3)
                self.MarketOrder(key, -quantity)
    
    
    def InitizalizeSymbolData(self, symbol, parameters):
        needed_period = max(parameters)+1
        if symbol not in self.symbol_data:
                self.symbol_data[symbol] = SymbolData(self, symbol, parameters)
        history = self.History(symbol, needed_period, Resolution.Hour)
        if not history.empty:
            self.symbol_data[symbol].WarmUpIndicators(history)

class SymbolData(object):
    def __init__(self, algorithm, symbol, parameters):
        self.symbol = symbol
        self.indicator = algorithm.MACD(symbol, *parameters, MovingAverageType.Simple, Resolution.Hour)
        self.is_buy = False
        self.is_sell = False
    
    def WarmUpIndicators(self, history):
        for index, row in history.loc[str(self.symbol)].iterrows():
            self.indicator.Update(index, row["close"])
    
    def ComputeStatus(self):
        if self.indicator.Signal.Current.Value > self.indicator.Current.Value:
            self.is_buy = True
            self.is_sell = False
        else: 
            self.is_sell = True
            self.is_buy = False