| Overall Statistics |
|
Total Orders 239 Average Win 0.32% Average Loss -0.13% Compounding Annual Return 1.022% Drawdown 2.700% Expectancy 0.141 Start Equity 1000000 End Equity 1024007.2 Net Profit 2.401% Sharpe Ratio -0.404 Sortino Ratio -0.548 Probabilistic Sharpe Ratio 12.947% Loss Rate 67% Win Rate 33% Profit-Loss Ratio 2.48 Alpha -0.004 Beta -0.021 Annual Standard Deviation 0.017 Annual Variance 0 Information Ratio -0.833 Tracking Error 0.203 Treynor Ratio 0.338 Total Fees $590.33 Estimated Strategy Capacity $2800000000.00 Lowest Capacity Asset CL XON0163K9O75 Portfolio Turnover 1.41% |
from AlgorithmImports import *
from QuantConnect.DataSource import *
class USFuturesSecurityMasterDataClassicAlgorithm (QCAlgorithm):
threshold = 0.01 # 1%
def initialize(self) -> None:
self.set_cash(1000000)
self.set_start_date(2019, 2, 1)
self.set_end_date(2021, 6, 1)
# Requesting data
self.continuous_contract = self.add_future(Futures.Energies.CRUDE_OIL_WTI,
data_normalization_mode = DataNormalizationMode.BACKWARDS_RATIO,
data_mapping_mode = DataMappingMode.OPEN_INTEREST,
contract_depth_offset = 0)
self.continuous_contract_symbol = self.continuous_contract.symbol
# Historical data
history = self.history(self.continuous_contract_symbol, 500, Resolution.MINUTE)
self.debug(f"We got {len(history)} items from our history request")
self.sma = self.SMA(self.continuous_contract_symbol, 10, Resolution.DAILY)
if not history.empty:
for time, row in history.droplevel(0).loc[self.continuous_contract_symbol].iterrows():
self.sma.update(IndicatorDataPoint(time, row.close))
def on_data(self, slice: Slice) -> None:
# Accessing data
for symbol, changed_event in slice.symbol_changed_events.items():
old_symbol = changed_event.old_symbol
new_symbol = changed_event.new_symbol
tag = f"Rollover - Symbol changed at {self.time}: {old_symbol} -> {new_symbol}"
quantity = self.portfolio[old_symbol].quantity
# Rolling over: to liquidate any position of the old mapped contract and switch to the newly mapped contract
self.liquidate(old_symbol, tag = tag)
if quantity != 0: self.market_order(new_symbol, quantity, tag = tag)
self.log(tag)
mapped_symbol = self.continuous_contract.mapped
if not (slice.bars.contains_key(self.continuous_contract_symbol) and self.sma.is_ready and mapped_symbol):
return
if slice.bars[self.continuous_contract_symbol].price > self.sma.current.value * (1+self.threshold) and not self.portfolio[mapped_symbol].is_long:
self.market_order(mapped_symbol, 1)
elif slice.bars[self.continuous_contract_symbol].price < self.sma.current.value * (1-self.threshold) and not self.portfolio[mapped_symbol].is_short:
self.market_order(mapped_symbol, -1)