Overall Statistics
Total Trades
150
Average Win
0.32%
Average Loss
-0.48%
Compounding Annual Return
-30.112%
Drawdown
19.600%
Expectancy
-0.096
Net Profit
-8.691%
Sharpe Ratio
-1.164
Probabilistic Sharpe Ratio
11.490%
Loss Rate
46%
Win Rate
54%
Profit-Loss Ratio
0.67
Alpha
-0.165
Beta
0.213
Annual Standard Deviation
0.241
Annual Variance
0.058
Information Ratio
0.533
Tracking Error
0.492
Treynor Ratio
-1.318
Total Fees
$332.81
#https://www.quantconnect.com/forum/discussion/2990/setting-custom-market-order-fill-model-for-options/p1
import numpy as np
import random

class CustomModelsAlgorithm(QCAlgorithm):
    '''Demonstration of using custom fee, slippage and fill models for modelling transactions in backtesting.
    QuantConnect allows you to model all orders as deeply and accurately as you need.'''

    def Initialize(self):
        self.SetStartDate(2020,1,1)   # Set Start Date
        self.security = self.AddEquity("LII", Resolution.Hour)
        self.lii = self.security.Symbol

        # set our models
        self.security.SetFillModel(CustomFillModel(self))


    def OnData(self, data):
        open_orders = self.Transactions.GetOpenOrders(self.lii)
        if len(open_orders) != 0: return

        if self.Time.day > 2 and self.security.Holdings.Quantity <= 0:
            quantity = self.CalculateOrderQuantity(self.lii, .5)
            self.Log("MarketOrder: " + str(quantity))
            self.MarketOrder(self.lii, quantity, True)   # async needed for partial fill market orders

        elif self.Time.day > 20 and self.security.Holdings.Quantity >= 0:
            quantity = self.CalculateOrderQuantity(self.lii, -.5)
            self.Log("MarketOrder: " + str(quantity))
            self.MarketOrder(self.lii, quantity, True)   # async needed for partial fill market orders

# inherit Immediate Fill Model
class CustomFillModel(ImmediateFillModel):
    def __init__(self, algorithm):
        self.algorithm = algorithm
        self.absoluteRemainingByOrderId = {}
        self.random = Random(1234)

    def MarketFill(self, asset, order):
        absoluteRemaining = order.AbsoluteQuantity

        if order.Id in self.absoluteRemainingByOrderId.keys():
            absoluteRemaining = self.absoluteRemainingByOrderId[order.Id]

        fill = super().MarketFill(asset, order)
        absoluteFillQuantity = int(min(absoluteRemaining, self.random.Next(0, 2*int(order.AbsoluteQuantity))))
        fill.FillQuantity = np.sign(order.Quantity) * absoluteFillQuantity
        
        if absoluteRemaining == absoluteFillQuantity:
            fill.Status = OrderStatus.Filled
            if self.absoluteRemainingByOrderId.get(order.Id):
                self.absoluteRemainingByOrderId.pop(order.Id)
        else:
            absoluteRemaining = absoluteRemaining - absoluteFillQuantity
            self.absoluteRemainingByOrderId[order.Id] = absoluteRemaining
            fill.Status = OrderStatus.PartiallyFilled
        self.algorithm.Log("CustomFillModel: " + str(fill))
        return fill