Skip to content

tradingmachine.orders.plan_parts.pre_open_venue

The pre_open venue of a plan: an order sent in the pre-open session so it trades at the opening auction's price.

UBI sends the order at at_time, 09:00:30 by default, through a time_from trigger of its own, so an order with this venue takes no trigger (pre_open_sets_its_time). The pre-open takes only LIMIT and MARKET orders, on NSE and BSE cash until 09:10, market orders until 09:05, and on NSE stock and index futures until 09:07; anything else, or an order sent after collection has closed, is refused with HTTP 400. Unlike most parts, a venue is an entry of the order's venue list rather than a one-key object.

Typical usage example:

part = order_part.OrderPart(venue=pre_open_venue.PreOpenVenue(at_time="09:02")) document = part.document()

PreOpenVenue

PreOpenVenue(*, at_time=None)

Bases: PlanPart

The pre-open session, with the time the order is sent into it.

Attributes:

Name Type Description
at_time

The str time of day the order is sent, such as 09:02, or None for UBI's default of 09:00:30.

Initialises the venue with the time the order is sent.

Parameters:

Name Type Description Default
at_time str | None

The str time of day in India while the pre-open takes orders, such as 09:02 or 09:00:30, or None for UBI's default of 09:00:30.

None
Source code in src/tradingmachine/orders/plan_parts/pre_open_venue.py
def __init__(
    self,
    *,
    at_time: str | None = None,
):
    """Initialises the venue with the time the order is sent.

    Args:
        at_time: The str time of day in India while the pre-open takes orders, such as `09:02` or `09:00:30`, or None for UBI's default of `09:00:30`.

    Raises:
        Nothing.
    """
    self.at_time = at_time

document

document()

Builds the venue entry UBI reads.

Returns:

Type Description
dict

A dict holding session set to pre_open, and at_time when it is not None. OrderPart puts it in a list of one under venue.

Examples:

Print the venue entry at UBI's default time:

from tradingmachine.orders.plan_parts import pre_open_venue

print(pre_open_venue.PreOpenVenue().document())

Print a limit buy at 1000 sent into the pre-open at two minutes past nine:

from tradingmachine.orders.plan_parts import fixed_pricing
from tradingmachine.orders.plan_parts import order_part
from tradingmachine.orders.plan_parts import pre_open_venue

part = order_part.OrderPart(
    pricing=fixed_pricing.FixedPricing(price=1000.0, order_type="LIMIT"),
    venue=pre_open_venue.PreOpenVenue(at_time="09:02"),
)
print(part.document())
Source code in src/tradingmachine/orders/plan_parts/pre_open_venue.py
def document(self) -> dict:
    """Builds the venue entry UBI reads.

    Returns:
        A dict holding `session` set to `pre_open`, and `at_time` when it is not None. `OrderPart` puts it in a list of one under `venue`.

    Raises:
        Nothing.

    Examples:
        Print the venue entry at UBI's default time:

        ```python
        from tradingmachine.orders.plan_parts import pre_open_venue

        print(pre_open_venue.PreOpenVenue().document())
        ```

        Print a limit buy at 1000 sent into the pre-open at two minutes past nine:

        ```python
        from tradingmachine.orders.plan_parts import fixed_pricing
        from tradingmachine.orders.plan_parts import order_part
        from tradingmachine.orders.plan_parts import pre_open_venue

        part = order_part.OrderPart(
            pricing=fixed_pricing.FixedPricing(price=1000.0, order_type="LIMIT"),
            venue=pre_open_venue.PreOpenVenue(at_time="09:02"),
        )
        print(part.document())
        ```
    """
    entry = {
        "session": "pre_open",
    }
    if self.at_time is not None:
        entry["at_time"] = self.at_time
    return entry

Example programs

Build a buy of Vodafone Idea sent into the pre-open session at two minutes past nine, so it trades at the opening auction's price

Run it with .venv/bin/python examples/orders/plan_parts/pre_open_venue/pre_open_venue/opening_auction_buy.py.

"""Build a buy of Vodafone Idea sent into the pre-open session at two minutes past nine, so it trades at the opening auction's price.

The program reads the share's last price and builds a limit buy 1% above it, which the auction fills at its single opening price if that price is at or below the limit. The order takes no trigger, because UBI sends it at the venue's `at_time` through a trigger of its own, and it is a `LIMIT` order, one of the two order types the pre-open takes. It prints the plan, and the venue entry alone at UBI's default time of 09:00:30. Nothing is sent to UBI's order routes.

Typical usage example:

  .venv/bin/python examples/orders/plan_parts/pre_open_venue/pre_open_venue/opening_auction_buy.py
"""

import json

from tradingmachine.assets import equities
from tradingmachine.orders.plan_parts import fixed_pricing
from tradingmachine.orders.plan_parts import order_part
from tradingmachine.orders.plan_parts import pre_open_venue


class OpeningAuctionBuy:
    """A limit buy sent into the pre-open session.

    Attributes:
        share: The tradingmachine.assets.equities.Equity for Vodafone Idea on the NSE.
    """

    def __init__(self):
        """Looks the share up.

        Raises:
            tradingmachine.assets.exceptions.InstrumentError: The share could not be found in UBI.
        """
        self.share = equities.Equity(exchange="nse", symbol="IDEA")

    def run(self) -> None:
        """Prints the plan and the default venue entry.

        Returns:
            None.

        Raises:
            ValueError: UBI has no last price for the share.
        """
        last_price = self.share.last_price
        if last_price is None:
            raise ValueError(f"UBI has no last price for {self.share!r}")
        plan = order_part.OrderPart(
            quantity=1000,
            product="cnc",
            pricing=fixed_pricing.FixedPricing(
                price=round(last_price * 1.01, 2),
                order_type="LIMIT",
            ),
            venue=pre_open_venue.PreOpenVenue(at_time="09:02"),
        )
        print(f"Last price of {self.share.symbol}: {last_price}")
        print(json.dumps(plan.document(), indent=2))
        print("The venue at UBI's default time:")
        print(json.dumps(pre_open_venue.PreOpenVenue().document(), indent=2))


if __name__ == "__main__":
    OpeningAuctionBuy().run()

Build an entry into Vodafone Idea at the opening auction, protected by a stop once it fills

Run it with .venv/bin/python examples/orders/plan_parts/pre_open_venue/pre_open_venue/opening_auction_entry_with_a_stop.py.

"""Build an entry into Vodafone Idea at the opening auction, protected by a stop once it fills.

The first plan of a then join is a market buy sent into the pre-open at UBI's default time of 09:00:30, which is before the 09:05 cut-off for market orders. Its fills are protected by a native stop 3% below the last price read now, placed once the auction has filled the entry and the market opens. It prints the plan. Nothing is sent to UBI's order routes.

Typical usage example:

  .venv/bin/python examples/orders/plan_parts/pre_open_venue/pre_open_venue/opening_auction_entry_with_a_stop.py
"""

import json

from tradingmachine.assets import equities
from tradingmachine.orders.plan_parts import fixed_pricing
from tradingmachine.orders.plan_parts import native_stop_pricing
from tradingmachine.orders.plan_parts import order_part
from tradingmachine.orders.plan_parts import pre_open_venue
from tradingmachine.orders.plan_parts import then_part


class AuctionEntryWithStop:
    """A pre-open market buy followed by a protecting stop.

    Attributes:
        share: The tradingmachine.assets.equities.Equity for Vodafone Idea on the NSE.
    """

    def __init__(self):
        """Looks the share up.

        Raises:
            tradingmachine.assets.exceptions.InstrumentError: The share could not be found in UBI.
        """
        self.share = equities.Equity(exchange="nse", symbol="IDEA")

    def run(self) -> None:
        """Prints the plan.

        Returns:
            None.

        Raises:
            ValueError: UBI has no last price for the share.
        """
        last_price = self.share.last_price
        if last_price is None:
            raise ValueError(f"UBI has no last price for {self.share!r}")
        stop_trigger = round(last_price * 0.97, 2)
        plan = then_part.ThenPart(
            first=order_part.OrderPart(
                pricing=fixed_pricing.FixedPricing(order_type="MARKET"),
                venue=pre_open_venue.PreOpenVenue(),
            ),
            each_fill=order_part.OrderPart(
                side="protect",
                pricing=native_stop_pricing.NativeStopPricing(
                    trigger_price=stop_trigger,
                    limit_price=round(stop_trigger - 0.05, 2),
                ),
            ),
        )
        print(f"Last price of {self.share.symbol}: {last_price}")
        print(json.dumps(plan.document(), indent=2))


if __name__ == "__main__":
    AuctionEntryWithStop().run()