Overall Statistics
Total Trades
60
Average Win
42.38%
Average Loss
-2.89%
Compounding Annual Return
517.514%
Drawdown
26.900%
Expectancy
3.172
Net Profit
615.845%
Sharpe Ratio
2.361
Loss Rate
73%
Win Rate
27%
Profit-Loss Ratio
14.64
Alpha
1.562
Beta
-0.048
Annual Standard Deviation
0.659
Annual Variance
0.434
Information Ratio
2.149
Tracking Error
0.662
Treynor Ratio
-32.296
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)
        
        # Request warmup data
        self.SetWarmup(slow_period + 1)

        # 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)
        
        # Plot EMAs
        self.PlotIndicator(
            self.target_crypto,
            self.fast,
            self.slow
        )
        
        # Plot MOM
        self.mom = self.MOM(self.target_crypto, (daily_period * 3))
        self.PlotIndicator(
            self.target_crypto,
            self.mom
        )
        
        # Plot RSI
        self.rsi_weekly = self.RSI(self.target_crypto, (daily_period * 3))
        self.PlotIndicator(
            self.target_crypto,
            self.rsi_weekly
        )

        # Plot Ultimate Oscilator
        self.ultosc = self.ULTOSC(
            self.target_crypto, 
            very_fast_period, 
            daily_period,
            weekly_period
        )
        self.PlotIndicator(
            self.target_crypto,
            self.ultosc,
        )
        
        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))

        # 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
            
        # 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
                #)