Trading Cryptocurrencies-Euro with QuantConnect´s Lean Engine

Officially QuantConnect´s Lean Engine does not support cryptocurrency trading in non-US dollar denominated accounts (yet). The procedure the engine uses to reach currency pair prices requires a USD starting point, so that if our crypto broker account is denominated in EUR (and nothing else) the live trading engine will not be able to determine correctly our cashbook positions.


It is still possible to launch automated trading algorithms in using, for example, Coinbase with a little workaround. This script will trade a Moving Average Convergence-Divergence signal for ETHEUR:

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


The numbers in bold type indicate the minimum amounts of both fiat currency (Euro) and crypto (ETH) to hold at any given moment. We will not trade all our available coins in any single moment as it may result in multiple orders that cannot be filled. Also, take into account the minimum order sizes for the broker, in this case, for Coinbase, here, by the way, part of the legal trading agreement. Before starting the script, make sure your Coinbase account holds both Euro and Ethereum, if needed be purchase the minimum amount of ETH possible so that the algorithm can resolve the Euro price with respect to US Dollar, needed at this point by the framework.


This is the back-test for this MACD strategy with ETHEUR, watch out for mounting trading fees, crypto trading has relatively high trading fees depending on the size of your account:


Remember that our publications are not financial advice. Ostirion.net does not hold any positions on any of the mentioned instruments at the time of publication. If you need further information, asset management support, automated trading strategy development or tactical strategy deployment you can contact us here.

44 views0 comments

Recent Posts

See All