Overall Statistics
Total Orders
105
Average Win
0.77%
Average Loss
-0.34%
Compounding Annual Return
1.211%
Drawdown
3.300%
Expectancy
0.911
Start Equity
1000000
End Equity
1166213.45
Net Profit
16.621%
Sharpe Ratio
-0.513
Sortino Ratio
-0.678
Probabilistic Sharpe Ratio
0.000%
Loss Rate
41%
Win Rate
59%
Profit-Loss Ratio
2.25
Alpha
-0.017
Beta
0.009
Annual Standard Deviation
0.031
Annual Variance
0.001
Information Ratio
-0.68
Tracking Error
0.144
Treynor Ratio
-1.798
Total Fees
$149.83
Estimated Strategy Capacity
$160000000000.00
Lowest Capacity Asset
KM Z5O7UGDUMN69
Portfolio Turnover
0.16%
Drawdown Recovery
1640
# region imports
from AlgorithmImports import *
# endregion

class Kospi200FuturesAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2013,11,1)
        self.set_cash(1_000_000)

        self._index = self.add_index("KM", market=Market.KRX)
        self._forex = self.add_forex("USDKRW")

        self._future = self.add_future(Futures.Indices.KOSPI_200,
            extended_market_hours=True,
            data_mapping_mode=DataMappingMode.LAST_TRADING_DAY,
            data_normalization_mode=DataNormalizationMode.BACKWARDS_RATIO,
            contract_depth_offset=0
        )
        # Filter to contracts expiring within 6 months (approx 182 days)
        self._future.set_filter(0, 182)
        # We will control open position with this order ticket
        self._ticket: OrderTicket = None

    def on_end_of_day(self, symbol: Symbol):
        if symbol.security_type in [SecurityType.INDEX, SecurityType.FOREX]:
            self.plot(symbol.value, 'EOD', self.securities[symbol].price)
        if symbol == self._future.mapped:
            self.plot('KM', symbol.value, self.securities[symbol].price)
        # Release the ticket on end of day
        if not self.portfolio.invested:
            self._ticket = None

    def on_data(self, data: Slice) -> None:
        if self.is_warming_up or self._ticket:
            return

        # Get the futures chain for our KM contract
        chain = data.future_chains.get(self._future.symbol)
        if not chain:
            return

        # Sort contracts by expiry and pick the nearest one with data
        contracts = sorted([c for c in chain if (c.expiry-self.time).days>1], key=lambda c: c.expiry)
        if not contracts:
            return

        front = contracts[0]

        # Place order on the front-month contract
        self._ticket = self.market_order(front.symbol, 1, tag=f'{self._future.mapped.value=}')