Skip to content

contango.trading.execution.backtest.orders.order_filler

contango.trading.execution.backtest.orders.order_filler

OrderFiller

OrderFiller(config: BacktesterConfig, event_bus: EventBus)

Fills all orders made by accepting OrderEvent instances and publishing filled events.

Initializes ExecutionEngine.

Parameters:

Name Type Description Default
config BacktesterConfig

The BacktesterConfig to determine fill behavior from.

required
event_bus EventBus

The event bus to publish filled events to.

required
Source code in src\contango\trading\execution\backtest\orders\order_filler.py
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
def __init__(
    self,
    config: BacktesterConfig,
    event_bus: EventBus
) -> None:
    """
    Initializes `ExecutionEngine`.

    Args:
        config: The `BacktesterConfig` to determine fill behavior from.
        event_bus: The event bus to publish filled events to.
    """
    self._config = config
    self._event_bus = event_bus

    self._last_market_event: MarketDataEvent | None = None
    self._last_portfolio_snapshot: PortfolioSnapshotEvent | None = None

collect_market_data

collect_market_data(market_data: MarketDataEvent) -> None

Collects & stores the current market event upon the event being published.

Source code in src\contango\trading\execution\backtest\orders\order_filler.py
56
57
58
59
60
def collect_market_data(self, market_data: MarketDataEvent) -> None:
    """
    Collects & stores the current market event upon the event being published.
    """
    self._last_market_event = market_data

collect_portfolio_snapshot

collect_portfolio_snapshot(event: PortfolioSnapshotEvent) -> None

Collects & stores the current portfolio snapshot upon the event being published.

Source code in src\contango\trading\execution\backtest\orders\order_filler.py
62
63
64
65
66
def collect_portfolio_snapshot(self, event: PortfolioSnapshotEvent) -> None:
    """
    Collects & stores the current portfolio snapshot upon the event being published.
    """
    self._last_portfolio_snapshot = event

fill_order_event

fill_order_event(order_event: OrderEvent) -> None

Publishes an accepted or rejected filled event order whenever an OrderEvent is created.

Parameters:

Name Type Description Default
order_event OrderEvent

The order event to process & create a FillOrder for.

required

Raises:

Type Description
RuntimeError

Upon an order being made before required events being injected into the OrderFiller.

Source code in src\contango\trading\execution\backtest\orders\order_filler.py
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
def fill_order_event(self, order_event: OrderEvent) -> None:
    """
    Publishes an accepted or rejected filled event order whenever an `OrderEvent` is created.

    Args:
        order_event: The order event to process & create a `FillOrder` for.

    Raises:
        RuntimeError: Upon an order being made before required events being injected into the `OrderFiller`.
    """
    market_event = self._last_market_event
    portfolio_snapshot = self._last_portfolio_snapshot

    if market_event is None:
        raise RuntimeError("Tried to execute orders before market event was registered in the order filler.")
    if portfolio_snapshot is None:
        raise RuntimeError("Tried to execute orders before a portfolio snapshot was registered in the order filler.")

    fill_price = self._resolve_fill_price(market_event)
    price_with_slippage = self._apply_slippage(order_event, fill_price)
    commission = self._calculate_commission(order_event)

    order_cost = price_with_slippage * order_event.quantity
    total_cost = order_cost + commission

    validation_result = BACKTESTER_FILL_POLICY.validate_rules(RuleContext(
        desired_quantity=order_event.quantity,
        current_position=portfolio_snapshot.position,
        total_cost=total_cost,
        current_cash=portfolio_snapshot.cash
    ))

    if validation_result is not None:
        fill_event = RejectedFillEvent(
            timestamp=market_event.timestamp,
            market_event=market_event,
            order_event=order_event,
            reason=validation_result
        )
    else:
        fill_event = AcceptedFillEvent(
            timestamp=market_event.timestamp,
            market_event=market_event,
            order_event=order_event,
            fill_price=price_with_slippage,
            total_cost=total_cost
        )

    self._event_bus.publish(fill_event)