Overall Statistics
Total Trades
60
Average Win
42.38%
Average Loss
-2.89%
Compounding Annual Return
520.496%
Drawdown
26.900%
Expectancy
3.172
Net Profit
615.845%
Sharpe Ratio
2.364
Loss Rate
73%
Win Rate
27%
Profit-Loss Ratio
14.64
Alpha
1.566
Beta
-0.049
Annual Standard Deviation
0.66
Annual Variance
0.435
Information Ratio
2.152
Tracking Error
0.663
Treynor Ratio
-32.002
Total Fees
$713.95
# WarmCryptoCrossover v0.03 (Py) 

from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Indicators")
AddReference("QuantConnect.Common")

from System import *
from QuantConnect import *
from QuantConnect.Data import *
from QuantConnect.Algorithm import *
from QuantConnect.Indicators import *
from datetime import datetime
import decimal as d
import numpy as np

class WarmupAlgorithm(QCAlgorithm):

    def Initialize(self):
        
        # define email address for buy/sell notifications
        # please change prior to Live deploy
        self.email_address = 'test@test.com'

        self.SetStartDate(2017,4,1)   #Set Start Date
        self.SetEndDate(2017,11,5)    #Set End Date
        self.SetCash(1000)           #Set Strategy Cash
        
        # define crypto we want to trade on
        # ETHUSD or LTCUSD or BTCUSD
        self.target_crypto = "ETHUSD"

        # Set brokerage to GDAX for cryptos
        self.SetBrokerageModel(BrokerageName.GDAX, AccountType.Cash)

        # Set crypto and time resolution
        self.AddCrypto(self.target_crypto, Resolution.Hour)
        
        # convience reference for price
        self.price = self.Securities[self.target_crypto].Price

        # Define windows in days for EMA
        # 168 hours in a week, 1440 minutes in a day
        very_fast_period = 2
        fast_period = 12
        slow_period = (fast_period * 10)
        medium_period = ((slow_period - fast_period) / 2) + fast_period
        very_slow_period = (slow_period * 3)
        daily_period = 24
        weekly_period = (daily_period * 7)
        monthly_period = (weekly_period * 30)

        # Define a fast and slow exponential moving average
        self.fast = self.EMA(self.target_crypto, fast_period)
        self.medium = self.EMA(self.target_crypto, medium_period)
        self.slow = self.EMA(self.target_crypto, slow_period)
        
        # Define average direction
        self.adx_arbitrary = self.ADX(self.target_crypto, 48)
        self.adx_fast = self.ADX(self.target_crypto, fast_period)
        self.adx_daily = self.ADX(self.target_crypto, daily_period)
        self.adx_weekly = self.ADX(self.target_crypto, weekly_period)
        self.adx_monthly = self.ADX(self.target_crypto, monthly_period)
        
        # Request warmup data
        self.SetWarmup(slow_period + 1)
        
        # Plot EMAs
        self.PlotIndicator(
            self.target_crypto,
            self.fast,
            self.medium,
            self.slow
        )
        
        # Plot ADX
        self.PlotIndicator(
            self.target_crypto,
            self.adx_daily,
        )
        
        self.first = True


    def OnData(self, data):
        if self.first and not self.IsWarmingUp:
            self.first = False
            self.Log("Fast: {0}".format(self.fast.Samples))
            self.Log("Medium: {0}".format(self.medium.Samples))
            self.Log("Slow: {0}".format(self.slow.Samples))
            self.Log("ADX >> {0}".format(self.adx_daily.Samples))

        # Determine holdings (# of units held) and price of unit
        holdings = self.Portfolio[self.target_crypto].Quantity

        # define a small tolerance on our checks to avoid bouncing
        if holdings > 0:
            tolerance = 0.0001
        else:
            tolerance = 0.0001
            
        self.Log("ADX >> {0}".format(self.adx_daily))
            
        # we only want to go long if we're currently short or flat
        if holdings <= 0:
            # if the fast is greater than the slow, we'll go long
            if self.fast.Current.Value > self.slow.Current.Value * d.Decimal(1 + tolerance):
                self.SetHoldings(self.target_crypto, 1)
                notify_message = "BUY >> {0} at {1}/unit".format(self.target_crypto,self.price)
                self.Log(notify_message)
                
                # Email notification of buy (only in Live environment)
                #self.Notify(
                #    address=self.email_address,
                #    subject='QuantConnect Algo Buy',
                #    message=notify_message
                #)

        # we only want to liquidate if we're currently long
        # if the fast is less than the slow we'll liquidate our long
        if holdings > 0:
            if self.fast.Current.Value < self.slow.Current.Value * d.Decimal(1 - tolerance):
                self.SetHoldings(self.target_crypto, 0)
                notify_message = "Sell >> {0} at {1}/unit".format(self.target_crypto,self.price)
                self.Log(notify_message)
                
                # Email notification of sell (only in Live environment)
                #self.Notify(
                #    address=self.email_address,
                #    subject='QuantConnect Algo Sell',
                #    message=notify_message
                #)