tradingmachine.orders.plan_parts.peg_pricing
¶
The peg pricing rule of a plan: a limit kept at a named place in the book and moved there as the book moves.
The reference is own_touch, the best price on the order's own side, so a buy sits on the bid; mid, halfway between the bid and the offer; or opposite_touch, the other side's best price, where the order fills at once. A positive offset_ticks moves the order away from filling and a negative one towards it. Every move passes UBI's repricing throttle, and a move that changes nothing is not sent. When the book gives no price as the order is sent, because nobody is on the side the reference reads, no live quote has arrived or the quote is marked stale, on_empty_book decides what happens: wait, UBI's default, keeps the order waiting for a tick that does, and refuse ends it refused, which a plan with nothing else placed answers with HTTP 409 and sends nothing.
Typical usage example:
pricing = peg_pricing.PegPricing(reference="own_touch", offset_ticks=1) document = pricing.document()
PegPricing
¶
PegPricing(*, reference=None, offset_ticks=None, follows=None, within_body_price=False, on_empty_book=None)
Bases: PlanPart
A pricing rule that keeps a limit at its reference in the book.
Attributes:
| Name | Type | Description |
|---|---|---|
reference |
The str place in the book, |
|
offset_ticks |
The int number of ticks away from the reference, positive away from filling and negative towards it, or None for UBI's default of 0. |
|
follows |
A bool that is False to price the order at its reference once when it is sent and leave it there, or None for UBI's default of True. |
|
within_body_price |
A bool that is True to treat the template's limit price as the worst price the order takes. |
|
on_empty_book |
The str |
Initialises the rule with its reference and settings.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
reference
|
str | None
|
The str place in the book, |
None
|
offset_ticks
|
int | None
|
The int number of ticks away from the reference, positive away from filling and negative towards it, or None for UBI's default of 0. |
None
|
follows
|
bool | None
|
A bool that is False to price the order at its reference once and leave it there, True to move it whenever the reference moves, or None for UBI's default of True. |
None
|
within_body_price
|
bool
|
A bool that is True to treat the template's limit price as the worst price the order takes, resting at that price when the book shows no reference. UBI refuses that price with HTTP 400 when it is not a whole number of ticks. |
False
|
on_empty_book
|
str | None
|
The str |
None
|
Source code in src/tradingmachine/orders/plan_parts/peg_pricing.py
document
¶
Builds the peg pricing object UBI reads, holding every setting that is not None.
Returns:
| Type | Description |
|---|---|
dict
|
A dict with the single key |
Examples:
Print a peg that sits on the order's own side of the book with UBI's defaults:
from tradingmachine.orders.plan_parts import peg_pricing
pricing = peg_pricing.PegPricing()
print(pricing.document())
Print a peg to the midpoint, one tick further from filling:
from tradingmachine.orders.plan_parts import peg_pricing
pricing = peg_pricing.PegPricing(reference="mid", offset_ticks=1)
print(pricing.document())
Print a peg priced once at the own touch and kept within the template's limit price:
from tradingmachine.orders.plan_parts import peg_pricing
pricing = peg_pricing.PegPricing(
reference="own_touch",
follows=False,
within_body_price=True,
)
print(pricing.document())
Print a peg two ticks through the other side's best price that is refused, rather than left waiting, when nobody is on that side, which is the pricing of a marketable_limit order:
from tradingmachine.orders.plan_parts import peg_pricing
pricing = peg_pricing.PegPricing(
reference="opposite_touch",
offset_ticks=-2,
on_empty_book="refuse",
)
print(pricing.document())
Source code in src/tradingmachine/orders/plan_parts/peg_pricing.py
Example programs¶
Build a buy of a share pegged to each of the three places in the book a peg can follow¶
Run it with .venv/bin/python examples/orders/plan_parts/peg_pricing/peg_pricing/bid_on_each_reference.py.
"""Build a buy of a share pegged to each of the three places in the book a peg can follow.
The program looks up Vodafone Idea and builds three orders, one pegged to its own side of the book, one to the midpoint a tick further from filling, and one to the other side's touch, which fills at once. It prints the order object UBI would read for each. Nothing is sent to UBI's order routes.
Typical usage example:
.venv/bin/python examples/orders/plan_parts/peg_pricing/peg_pricing/bid_on_each_reference.py
"""
import json
from tradingmachine.assets import equities
from tradingmachine.orders.plan_parts import order_part
from tradingmachine.orders.plan_parts import peg_pricing
class PegReferences:
"""Three pegged buys of Vodafone Idea, one for each reference.
Attributes:
share: The tradingmachine.assets.equities.Equity for Vodafone Idea on the NSE.
"""
def __init__(self):
"""Looks up the share.
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 three orders' objects.
Returns:
None.
Raises:
Nothing.
"""
rules = {
"on the bid": peg_pricing.PegPricing(reference="own_touch"),
"a tick below the midpoint": peg_pricing.PegPricing(
reference="mid",
offset_ticks=1,
),
"on the offer, filling at once": peg_pricing.PegPricing(
reference="opposite_touch",
),
}
for description, rule in rules.items():
part = order_part.OrderPart(
instrument=self.share,
transaction_type="buy",
quantity=1,
pricing=rule,
)
print(f"Buy of {self.share.symbol} pegged {description}:")
print(json.dumps(part.document(), indent=2))
if __name__ == "__main__":
PegReferences().run()
Build a buy priced once at the bid and never above a limit worked out from the last price¶
Run it with .venv/bin/python examples/orders/plan_parts/peg_pricing/peg_pricing/one_shot_bid_within_a_limit.py.
"""Build a buy priced once at the bid and never above a limit worked out from the last price.
The program reads Vodafone Idea's last price and builds a plan order whose template is a limit buy 1% above it, with one order pegged to its own side of the book that does not follow it afterwards and treats the template's limit as the worst price it takes. This is how each purchase of UBI's accumulation type is priced. It prints the plan's synthetic object. The plan order is only built; nothing is sent to UBI's order routes.
Typical usage example:
.venv/bin/python examples/orders/plan_parts/peg_pricing/peg_pricing/one_shot_bid_within_a_limit.py
"""
import json
from tradingmachine.assets import equities
from tradingmachine.orders import plan
from tradingmachine.orders.plan_parts import order_part
from tradingmachine.orders.plan_parts import peg_pricing
class OneShotBid:
"""A buy of Vodafone Idea priced once at the bid, within a limit.
Attributes:
share: The tradingmachine.assets.equities.Equity for Vodafone Idea on the NSE.
"""
def __init__(self):
"""Looks up the share.
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 limit and the plan's synthetic object.
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}")
limit_price = round(last_price * 1.01, 2)
order = plan.PlanOrder(
self.share,
transaction_type="buy",
product="mis",
order_type="limit",
quantity=1,
price=limit_price,
plan=order_part.OrderPart(
pricing=peg_pricing.PegPricing(
reference="own_touch",
follows=False,
within_body_price=True,
),
),
)
print(f"Last price of {self.share.symbol}: {last_price}")
print(f"Template limit, the most the buy pays: {limit_price}")
print(json.dumps(order.synthetic, indent=2))
if __name__ == "__main__":
OneShotBid().run()