Overall Statistics
Total Trades
9
Average Win
45.92%
Average Loss
-16.85%
Compounding Annual Return
340.068%
Drawdown
34.400%
Expectancy
1.793
Net Profit
228.255%
Sharpe Ratio
2.011
Loss Rate
25%
Win Rate
75%
Profit-Loss Ratio
2.72
Alpha
1.168
Beta
0.274
Annual Standard Deviation
0.597
Annual Variance
0.356
Information Ratio
1.811
Tracking Error
0.598
Treynor Ratio
4.386
Total Fees
$0.00
# WarmCryptoCrossover (Py) v0.01

import clr
from clr import AddReference

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

from System import *
from QuantConnect import *
from QuantConnect.Data import *
from QuantConnect.Algorithm import *
from QuantConnect.Indicators import *

import decimal as d
import numpy as np

class CryptoWarmupMovingAverageCross(QCAlgorithm):
    
    def Initialize(self):
        
        self.SetStartDate(2017, 1, 1)  # Set Start Date
        self.SetEndDate(2017, 10, 19)  # Set End Date
        self.SetCash(10000)  # Set Strategy Cash

        # Set brokerage we are using: GDAX for cryptos
        #self.SetBrokerageModel(BrokerageName.GDAX, AccountType.Cash)

        # Set crypto to BTC at 1 hour resolution
        self.AddCrypto("BTCUSD", Resolution.Hour)

        # Define windows in days for EMA
        fast_period = 15
        slow_period = 30

        # create a fast exponential moving average at daily resolution
        self.fast = self.EMA("BTCUSD", fast_period, Resolution.Daily)

        # create a slow exponential moving average at daily resolution
        self.slow = self.EMA("BTCUSD", slow_period, Resolution.Daily)

        # "slow_period + 1" because rolling window waits for one to fall off the back to be considered ready
        # History method returns a dict with a pandas.DataFrame
        history = self.History(["BTCUSD"], slow_period + 1)
        
        # prints out the tail of the dataframe
        self.Log(str(history.loc["BTCUSD"].tail()))
        self.Log(str(history.loc["BTCUSD"].head()))

        # Populate warmup data
        for index, row in history.loc["BTCUSD"].iterrows():
            self.fast.Update(index, row["close"])
            self.slow.Update(index, row["close"])

        # Log warmup status
        self.Log(
            "FAST {0} READY. Samples: {1}".format("IS" if self.fast.IsReady else "IS NOT", self.fast.Samples))
        self.Log(
            "SLOW {0} READY. Samples: {1}".format("IS" if self.slow.IsReady else "IS NOT", self.slow.Samples))

        self.previous = None

    def OnData(self, data):

        # wait for our slow ema to fully initialize
        if not self.slow.IsReady:
            return

        # only once per day
        if self.previous is not None and self.previous.date() == self.Time.date():
            return

        # define a small tolerance on our checks to avoid bouncing
        tolerance = 0.00015

        # Determine number of BTC held
        holdings = self.Portfolio["BTCUSD"].Quantity

        # Log stats
        #self.Log("Holding {} BTCUSD @ {}".format(str(holdings), holdings * self.Securities["BTCUSD"].Price)))

        # 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.Log("BUY  >> {0}".format(self.Securities["BTCUSD"].Price))
                self.SetHoldings("BTCUSD", 1)

        # 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 and self.fast.Current.Value < self.slow.Current.Value:
            self.Log("SELL >> {0}".format(self.Securities["BTCUSD"].Price))
            self.SetHoldings("BTCUSD", 0)

        self.previous = self.Time