| Overall Statistics |
|
Total Trades 11 Average Win 13.89% Average Loss -0.73% Compounding Annual Return 23.912% Drawdown 15.000% Expectancy 11.067 Net Profit 23.964% Sharpe Ratio 1.009 Probabilistic Sharpe Ratio 46.702% Loss Rate 40% Win Rate 60% Profit-Loss Ratio 19.11 Alpha 0.082 Beta 0.604 Annual Standard Deviation 0.184 Annual Variance 0.034 Information Ratio 0.08 Tracking Error 0.178 Treynor Ratio 0.307 Total Fees $353.21 Estimated Strategy Capacity $1200000.00 Lowest Capacity Asset CL XX0ATS17OJB5 Portfolio Turnover 2.13% |
#region imports
from AlgorithmImports import *
#endregion
# region imports
# Import the libraries
from QuantConnect.Data.UniverseSelection import *
from datetime import timedelta
from QuantConnect.Algorithm.Framework.Risk import *
# Define the class
class MomentumFuturesAlgorithm(QCAlgorithm):
def Initialize(self):
# Set the start and end dates
self.SetStartDate(2020,12, 1)
self.SetEndDate(2021, 12, 1)
# Set the cash amount
self.SetCash(1000000)
# self.contractSymbol=None
# Add a futures contract
self.future = self.AddFuture(Futures.Energies.CrudeOilWTI, Resolution.Hour)
# self.sym = future1.Symbol
# Set the filter for the futures contract
self.future.SetFilter(timedelta(0), timedelta(182))
# benchmark = self.AddEquity("SPY")
# self.SetBenchmark(benchmark.Symbol)
# Define the trade size
self.tradeSize = 0.062
# Define the entry and exit thresholds
self.entryThreshold = 40
self.exitThreshold = 70
# Define the stop loss percentage
self.stopLossPct = 0.005
# Define the roll forward date as 2 days before expiration
self.rollForwardDate = timedelta(2)
# Initialize the variables for holding the contract and the order ticket
self.contract = None
self.isLong = 0
# Add a maximum drawdown risk management model with 15% threshold
# self.SetRiskManagement(MaximumDrawdownPercentPortfolio(0.01))
# self.SetExecution(ImmediateExecutionModel())
# Add a historical value at risk risk management model with 5% threshold and 99% confidence level
# self.SetRiskManagement(HistoricalVaR(0.05, 0.99))
def OnData(self,slice):
# hist = self.History([Futures.Energies.CrudeOilWTI],self.Time-timedelta(241),self.Time,Resolution.Hour)
# hist = hist['close'].unstack(level =0).pct_change().dropna()
# var = np.quantile(hist,0.01)
# self.Log(var)
# Check if we have any open positions
if not self.Portfolio.Invested:
# self.contract = [contract for chain in slice.FutureChains.Values for contract in chain.Contracts.Values]
# self.contract = sorted(self.contract, key = lambda x: x.Expiry, reverse=False)
for chain in slice.FutureChains:
contracts = list(filter(lambda x: x.Expiry > self.Time, chain.Value))
if len(contracts) == 0:
continue
front = sorted(contracts, key = lambda x: x.Expiry, reverse=True)[0]
self.contract = front
price = slice[front.Symbol].Close
if self.RSI(front.Symbol, 20, Resolution.Hour).Current.Value < self.entryThreshold:
# Enter a long position and place a limit order to exit at a higher price
self.SetHoldings(front.Symbol, self.tradeSize)
self.isLong = 1
elif self.RSI(front.Symbol, 20, Resolution.Hour).Current.Value > self.exitThreshold:
# Enter a short position and place a limit order to exit at a lower price
self.SetHoldings(front.Symbol, -self.tradeSize)
self.isLong = -1
else:
# Get the current price of the contract
for chain in slice.FutureChains:
contracts = list(filter(lambda x: x.Expiry > self.Time, chain.Value))
if len(contracts) == 0:
continue
front = sorted(contracts, key = lambda x: x.Expiry, reverse=True)[-1]
# self.contractSymbol = front.Symbol
price = slice[front.Symbol].Close
# Check if we need to exit the position based on the momentum indicator or the stop loss
if (self.Portfolio[front.Symbol].IsLong and self.RSI(front.Symbol, 20, Resolution.Hour).Current.Value > self.exitThreshold) or \
(self.Portfolio[front.Symbol].IsShort and self.RSI(front.Symbol, 20, Resolution.Hour).Current.Value < self.entryThreshold) or \
(self.Portfolio[front.Symbol].UnrealizedProfitPercent < -self.stopLossPct):
# Liquidate the position and cancel any open orders
self.Liquidate(front.Symbol)
self.isLong = 0
# Log the exit signal and the price
#self.Log("Exit signal: {0}, Price: {1}".format(self.mom.Current.Value, price))
# Reset the contract and the order ticket variables
self.contract = None
elif self.Time + self.rollForwardDate > self.contract.Expiry:
self.Liquidate(self.contract.Symbol)
self.contract = front
self.SetHoldings(front.Symbol, self.isLong * self.tradeSize)