Overall Statistics
Total Trades
0
Average Win
0%
Average Loss
0%
Compounding Annual Return
0%
Drawdown
0%
Expectancy
0
Net Profit
0%
Sharpe Ratio
0
Probabilistic Sharpe Ratio
0%
Loss Rate
0%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
0
Beta
0
Annual Standard Deviation
0
Annual Variance
0
Information Ratio
1.893
Tracking Error
0.16
Treynor Ratio
0
Total Fees
$0.00
import typing
from QuantConnect.Securities.Future import Future
from collections import deque


# noinspection DuplicatedCode
class AdvancedCopulaMethod(QCAlgorithm):
    consolidator_by_symbol: typing.Dict[Symbol, TradeBarConsolidator] = {}
    day: typing.Optional[int] = None
    month: typing.Optional[int] = None

    active_contracts: typing.Dict[Symbol, deque] = {}
    contract_to_parent_map: typing.Dict[Symbol, Symbol] = {}

    def Initialize(self):
        self.SetStartDate(2020, 1, 5)
        self.SetEndDate(2020, 3, 1)
        self.SetCash(1000000)

        universe: typing.Dict[str, Future] = {s: self.AddFuture(s, Resolution.Minute) for s in self.tickers}
        [future.SetFilter(timedelta(0), timedelta(90)) for future in universe.values()]

        self.active_contracts = {future.Symbol: deque(maxlen=3) for future in universe.values()}

    # noinspection SpellCheckingInspection,DuplicatedCode
    def OnData(self, data: Slice):
        if self.day == self.Time.day:
            return
        self.Debug(f"OnData called on {self.Time}")
        contracts_in_use = []
        for chain in data.FutureChains.Values:
            contracts = chain.Contracts
            if len(contracts) == 0:
                continue
            sorted_by_oi_contracts = sorted(contracts.Values, key=lambda k: k.OpenInterest, reverse=True)
            popular_contracts = sorted_by_oi_contracts[:3]
            contracts_in_use.extend([s.Symbol for s in popular_contracts])
            for contract in popular_contracts:
                if contract.Symbol not in self.contract_to_parent_map:
                    self.contract_to_parent_map[contract.Symbol] = chain.Symbol
                if contract.Symbol not in self.consolidator_by_symbol:
                    self.consolidate_future(contract)

        if self.Time.month != self.month and self.Time.weekday() == 2:
            not_popular_contracts = [s for s in self.consolidator_by_symbol.keys() if s not in contracts_in_use]
            self.Debug([s.Value for s in not_popular_contracts])
            for symbol in not_popular_contracts:
                consolidator = self.consolidator_by_symbol.pop(symbol)
                self.SubscriptionManager.RemoveConsolidator(symbol, consolidator)
            self.month = self.Time.month
        self.day = self.Time.day

    def consolidate_future(self, contract):
        dailyConsolidator = TradeBarConsolidator(timedelta(days=1))
        dailyConsolidator.DataConsolidated += self.DailyHandler
        self.SubscriptionManager.AddConsolidator(contract.Symbol, dailyConsolidator)
        self.consolidator_by_symbol[contract.Symbol] = dailyConsolidator

    def DailyHandler(self, sender: DataConsolidator, bar: TradeBar):
        pass

    # noinspection SpellCheckingInspection,DuplicatedCode
    @property
    def tickers(self):
        indices = [
            Futures.Indices.SP500EMini,
            Futures.Indices.SP400MidCapEmini,
            Futures.Indices.Dow30EMini,
            Futures.Indices.Russell2000EMini,

            Futures.Indices.Nikkei225Dollar,
            Futures.Indices.USDDenominatedIbovespa,

            Futures.Indices.SPGSCICommodity,
            Futures.Indices.BloombergCommodityIndex,

            Futures.Indices.VIX,
        ]

        metals = [
            Futures.Metals.Gold,
            Futures.Metals.Silver,
            Futures.Metals.Platinum,
            Futures.Metals.Palladium,
            Futures.Metals.Copper,
        ]

        grains = [
            Futures.Grains.Wheat,
            Futures.Grains.Corn,
            Futures.Grains.Soybeans,
            Futures.Grains.Oats,
        ]

        tickers = indices + metals + grains

        return tickers