| Overall Statistics |
|
Total Orders 194 Average Win 4.96% Average Loss -3.91% Compounding Annual Return -7.486% Drawdown 44.400% Expectancy -0.080 Start Equity 100000 End Equity 67753.34 Net Profit -32.247% Sharpe Ratio -0.196 Sortino Ratio -0.237 Probabilistic Sharpe Ratio 0.212% Loss Rate 59% Win Rate 41% Profit-Loss Ratio 1.27 Alpha -0.037 Beta -0.217 Annual Standard Deviation 0.271 Annual Variance 0.073 Information Ratio -0.39 Tracking Error 0.32 Treynor Ratio 0.244 Total Fees $558.22 Estimated Strategy Capacity $610000000.00 Lowest Capacity Asset ZW YY8E90VXTCTH Portfolio Turnover 8.28% Drawdown Recovery 1056 |
#region imports
from AlgorithmImports import *
#endregion
class CommidityMomentumEffect(QCAlgorithm):
def initialize(self):
self.set_start_date(self.end_date - timedelta(5*365))
self.set_cash(100000)
self.settings.seed_initial_prices = True
symbols = [
Futures.Meats.LIVE_CATTLE,
Futures.Meats.FEEDER_CATTLE,
Futures.Meats.LEAN_HOGS,
Futures.Energy.CRUDE_OIL_WTI,
Futures.Energy.GASOLINE,
Futures.Grains.WHEAT,
Futures.Grains.SOYBEANS,
Futures.Grains.CORN
]
period = 252
self._futures = []
for symbol in symbols:
future = self.add_future(symbol,
resolution=Resolution.MINUTE,
extended_market_hours=True,
data_normalization_mode=DataNormalizationMode.BACKWARDS_RATIO,
data_mapping_mode=DataMappingMode.OPEN_INTEREST,
contract_depth_offset=0
)
future.set_leverage(1)
future.multiplier = future.symbol_properties.contract_multiplier
future.roc = self.roc(future.symbol, period, Resolution.DAILY)
self.warm_up_indicator(future.symbol, future.roc, Resolution.DAILY)
self._futures.append(future)
# Rebalance the portfolio every month
self.schedule.on(
self.date_rules.month_start('SPY'),
self.time_rules.after_market_open('SPY', 30),
self._rebalance
)
def _rebalance(self):
tradable_futures = [f for f in self._futures if f.roc.is_ready and f.mapped]
number_futures = int(0.25*len(tradable_futures))
# sorted futures by 12-month return reversely
sorted_roc = sorted(tradable_futures, key=lambda f: f.roc.current.value, reverse=True)
longs = [f for f in sorted_roc[:number_futures]]
shorts = [f for f in sorted_roc[-number_futures:]]
for symbol, security_holding in self.portfolio.items():
# liquidate the futures which is no longer in the trading list
if security_holding.invested and symbol not in [f.mapped for f in longs + shorts]:
self.liquidate(symbol)
self._trade(longs, 0.5/number_futures)
self._trade(shorts, -0.5/number_futures)
def _trade(self, futures, weight):
for f in futures:
qty = self.calculate_order_quantity(f.mapped, weight) // f.multiplier
if qty:
self.market_order(f.mapped, qty)