Adds SimpleCustomFillModel to CustomModelsAlgorithm (#7498)
* Adds `SimpleCustomFillModel` to `CustomModelsAlgorithm` The simple fill model shows how to implement a simpler version of the most popular order fills: Market, Stop Market and Limit. This model was tested on QuantConnect Cloud, and will serve as additonal example, since we don't have an example that does not reuse the method of the base class. * Handles Tick Resolution Case Tick-resolution data doesn't have TradeBar. We can use the security price, since it represents a trade (`TickTrade`).
This commit is contained in:
committed by
GitHub
parent
78a9b80bbf
commit
cbccb6e5cf
@@ -117,3 +117,66 @@ class CustomBuyingPowerModel(BuyingPowerModel):
|
||||
hasSufficientBuyingPowerForOrderResult = HasSufficientBuyingPowerForOrderResult(True)
|
||||
self.algorithm.Log(f"CustomBuyingPowerModel: {hasSufficientBuyingPowerForOrderResult.IsSufficient}")
|
||||
return hasSufficientBuyingPowerForOrderResult
|
||||
|
||||
# The simple fill model shows how to implement a simpler version of
|
||||
# the most popular order fills: Market, Stop Market and Limit
|
||||
class SimpleCustomFillModel(FillModel):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
def _create_order_event(self, asset, order):
|
||||
utcTime = Extensions.ConvertToUtc(asset.LocalTime, asset.Exchange.TimeZone)
|
||||
return OrderEvent(order, utcTime, OrderFee.Zero)
|
||||
|
||||
def _set_order_event_to_filled(self, fill, fill_price, fill_quantity):
|
||||
fill.Status = OrderStatus.Filled
|
||||
fill.FillQuantity = fill_quantity
|
||||
fill.FillPrice = fill_price
|
||||
return fill
|
||||
|
||||
def _get_trade_bar(self, asset, orderDirection):
|
||||
trade_bar = asset.Cache.GetData[TradeBar]()
|
||||
if trade_bar: return trade_bar
|
||||
|
||||
# Tick-resolution data doesn't have TradeBar, use the asset price
|
||||
price = asset.Price
|
||||
return TradeBar(asset.LocalTime, asset.Symbol, price, price, price, price, 0)
|
||||
|
||||
def MarketFill(self, asset, order):
|
||||
fill = self._create_order_event(asset, order)
|
||||
if order.Status == OrderStatus.Canceled: return fill
|
||||
|
||||
return self._set_order_event_to_filled(fill,
|
||||
asset.Cache.AskPrice \
|
||||
if order.Direction == OrderDirection.Buy else asset.Cache.BidPrice,
|
||||
order.Quantity)
|
||||
|
||||
def StopMarketFill(self, asset, order):
|
||||
fill = self._create_order_event(asset, order)
|
||||
if order.Status == OrderStatus.Canceled: return fill
|
||||
|
||||
stop_price = order.StopPrice
|
||||
trade_bar = self._get_trade_bar(asset, order.Direction)
|
||||
|
||||
if order.Direction == OrderDirection.Sell and trade_bar.Low < stop_price:
|
||||
return self._set_order_event_to_filled(fill, stop_price, order.Quantity)
|
||||
|
||||
if order.Direction == OrderDirection.Buy and trade_bar.High > stop_price:
|
||||
return self._set_order_event_to_filled(fill, stop_price, order.Quantity)
|
||||
|
||||
return fill
|
||||
|
||||
def LimitFill(self, asset, order):
|
||||
fill = self._create_order_event(asset, order)
|
||||
if order.Status == OrderStatus.Canceled: return fill
|
||||
|
||||
limit_price = order.LimitPrice
|
||||
trade_bar = self._get_trade_bar(asset, order.Direction)
|
||||
|
||||
if order.Direction == OrderDirection.Sell and trade_bar.High > limit_price:
|
||||
return self._set_order_event_to_filled(fill, limit_price, order.Quantity)
|
||||
|
||||
if order.Direction == OrderDirection.Buy and trade_bar.Low < limit_price:
|
||||
return self._set_order_event_to_filled(fill, limit_price, order.Quantity)
|
||||
|
||||
return fill
|
||||
|
||||
Reference in New Issue
Block a user