Overall Statistics Total Trades 2539 Average Win 1.89% Average Loss -2.05% Compounding Annual Return 13.700% Drawdown 59.500% Expectancy 0.069 Net Profit 261.320% Sharpe Ratio 0.542 Loss Rate 44% Win Rate 56% Profit-Loss Ratio 0.92 Alpha 0.17 Beta 0.083 Annual Standard Deviation 0.335 Annual Variance 0.112 Information Ratio 0.135 Tracking Error 0.366 Treynor Ratio 2.183 Total Fees \$0.00
#
# A 20-day moving average of WTI/Brent spread is calculated each day. If the current spread value is above SMA 20 then we enter a short position
# in the spread on close (betting that the spread will decrease to the fair value represented by SMA 20). The trade is closed at the close of the
# trading day when the spread crosses below fair value. If the current spread value is below SMA 20 then we enter a long position betting that
# the spread will increase and the trade is closed at the close of the trading day when the spread crosses above fair value.

from collections import deque
import numpy as np

def Initialize(self):
self.SetStartDate(2009, 1, 1)
self.SetEndDate(2019, 1, 1)
self.SetCash(100000)

self.symbols = [
"CME_CL1",  # Crude Oil Futures, Continuous Contract
"ICE_B1"    # Brent Crude Oil Futures, Continuous Contract
]

# True -> Quantpedia data
# False -> Quandl free data
self.use_quantpedia_data = True

if not self.use_quantpedia_data:
self.symbols = ['CHRIS/' + x for x in self.symbols]

for symbol in self.symbols:
data = None
if self.use_quantpedia_data:
data = self.AddData(QuantpediaFutures, symbol, Resolution.Daily)
else:
data = self.AddData(QuandlFutures, symbol, Resolution.Daily)
#data.SetLeverage(2)

def OnData(self, data):
symbol1 = self.symbols
symbol2 = self.symbols

if self.Securities.ContainsKey(symbol1) and self.Securities.ContainsKey(symbol2):
price1 = self.Securities[symbol1].Price
price2 = self.Securities[symbol2].Price
if price1 != 0 and price2 != 0:
spread = price1 - price2

# MA calculation
spreads = [x for x in self.spread]

if self.Portfolio[symbol1].IsLong:
self.Liquidate(symbol1)

if not self.Portfolio[symbol1].IsShort:
self.SetHoldings(symbol1, -1)
if self.Portfolio[symbol1].IsShort:
self.Liquidate(symbol1)

if not self.Portfolio[symbol1].IsLong:
self.SetHoldings(symbol1, 1)

# Quantpedia data
class QuantpediaFutures(PythonData):
def GetSource(self, config, date, isLiveMode):
return SubscriptionDataSource("https://quantpedia.com/backtesting_data/futures/{0}.csv".format(config.Symbol), SubscriptionTransportMedium.RemoteFile, FileFormat.Csv)

def Reader(self, config, line, date, isLiveMode):
data = QuantpediaFutures()
data.Symbol = config.Symbol

try:
if not line.isdigit(): return None
split = line.split(';')

data.Time = datetime.strptime(split, "%d.%m.%Y") + timedelta(days=1)
data['settle'] = float(split)
data.Value = float(split)
except:
return None

return data

# Quandl free data
class QuandlFutures(PythonQuandl):
def __init__(self):
self.ValueColumnName = "settle"