Overall Statistics |
Total Trades 81 Average Win 5.93% Average Loss -4.00% Compounding Annual Return 0% Drawdown 231.100% Expectancy 0.179 Net Profit -321.788% Sharpe Ratio -0.194 Probabilistic Sharpe Ratio 0.492% Loss Rate 52% Win Rate 48% Profit-Loss Ratio 1.48 Alpha -1.014 Beta -0.069 Annual Standard Deviation 5.15 Annual Variance 26.518 Information Ratio -0.154 Tracking Error 5.177 Treynor Ratio 14.405 Total Fees $0.00 |
# https://quantpedia.com/strategies/trading-wti-brent-spread/ # # 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 class WTI_BRENT_Spread(QCAlgorithm): def Initialize(self): self.SetStartDate(2020, 1, 1) self.SetEndDate(2020, 6, 28) self.SetCash(100000) self.symbols = [ "CME_CL1", # Crude Oil Futures, Continuous Contract "ICE_B1" # Brent Crude Oil Futures, Continuous Contract ] self.spread = deque(maxlen=2) # True -> Quantpedia data # False -> Quandl free data self.use_quantpedia_data = False 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[0] symbol2 = self.symbols[1] 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 self.spread.append(spread) # MA calculation if len(self.spread) == self.spread.maxlen: spreads = [x for x in self.spread] spread_ma20 = np.average(spreads) current_spread = spreads[-1] if current_spread > spread_ma20: if self.Portfolio[symbol1].IsLong: self.Liquidate(symbol1) if not self.Portfolio[symbol1].IsShort: self.SetHoldings(symbol1, -1) elif current_spread < spread_ma20: 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): #algo.Debug("http://data.quantpedia.com/backtesting_data/futures/{0}.csv".format(config.Symbol.Value)) return SubscriptionDataSource("http://data.quantpedia.com/backtesting_data/futures/{0}.csv".format(config.Symbol.Value), SubscriptionTransportMedium.RemoteFile, FileFormat.Csv) def Reader(self, config, line, date, isLiveMode): data = QuantpediaFutures() data.Symbol = config.Symbol try: if not line[0].isdigit(): return None split = line.split(';') data.Time = datetime.strptime(split[0], "%d.%m.%Y") + timedelta(days=1) data['settle'] = float(split[1]) data.Value = float(split[1]) except: return None return data # Quandl free data class QuandlFutures(PythonQuandl): def __init__(self): self.ValueColumnName = "settle"