tradingmachine.orders.plan_parts.iceberg_execution
¶
The iceberg execution of a plan: only part of the order shown at a time.
The order is sent as pieces of visible_quantity, the next only once the last has filled. Each piece may vary by up to randomise_percent either way, worked out from the parent's id and the number of pieces sent, so another trader cannot spot a repeating size; UBI's default is 0, no variation, and a varied piece is brought to the nearest whole number of lots, at least one. A piece that is cancelled or rejected rather than filled stops the iceberg.
An iceberg can nest on either side. As the outer execution it releases its pieces as slices for an inner one to work, and as the inner execution it shows each slice of a TwapExecution, VwapExecution, FrontLoadedExecution, ParticipationExecution or another iceberg a little at a time.
Typical usage example:
execution = iceberg_execution.IcebergExecution(visible_quantity=10) part = order_part.OrderPart(execution=execution) document = part.document()
IcebergExecution
¶
Bases: PlanPart
An execution that shows a small piece of the order at a time and sends the next once it has filled.
Attributes:
| Name | Type | Description |
|---|---|---|
visible_quantity |
The int size of each piece before any variation, at least 1. |
|
randomise_percent |
The int percentage, 0 to 99, by which a piece may vary either way, or None for UBI's default of 0. |
Initialises the execution with its piece size.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
visible_quantity
|
int
|
The int size of each piece before any variation, at least 1. |
required |
randomise_percent
|
int | None
|
The int percentage, 0 to 99, by which a piece may vary either way, or None for UBI's default of 0. |
None
|
Source code in src/tradingmachine/orders/plan_parts/iceberg_execution.py
document
¶
Builds the iceberg execution object UBI reads.
Returns:
| Type | Description |
|---|---|
dict
|
A dict with the single key |
Examples:
Print an iceberg that shows ten units at a time:
from tradingmachine.orders.plan_parts import iceberg_execution
execution = iceberg_execution.IcebergExecution(visible_quantity=10)
print(execution.document())
Print an iceberg whose pieces vary by up to a fifth either way:
from tradingmachine.orders.plan_parts import iceberg_execution
execution = iceberg_execution.IcebergExecution(
visible_quantity=50,
randomise_percent=20,
)
print(execution.document())
Print an order sent as six TWAP slices over an hour, each slice shown as an iceberg of ten:
from tradingmachine.orders.plan_parts import iceberg_execution
from tradingmachine.orders.plan_parts import order_part
from tradingmachine.orders.plan_parts import twap_execution
part = order_part.OrderPart(
execution=twap_execution.TwapExecution(
slices=6,
over_minutes=60,
),
inner_execution=iceberg_execution.IcebergExecution(
visible_quantity=10,
),
)
print(part.document())
Source code in src/tradingmachine/orders/plan_parts/iceberg_execution.py
Example programs¶
Build icebergs that rest a little below the market, with fixed and with varied piece sizes¶
Run it with .venv/bin/python examples/orders/plan_parts/iceberg_execution/iceberg_execution/hidden_size_below_the_market.py.
"""Build icebergs that rest a little below the market, with fixed and with varied piece sizes.
The program reads Vodafone Idea's last price and tick size and builds two orders for 2000 shares limited two ticks below the last price, one showing 200 at a time and one whose pieces vary by up to a quarter either way so other traders cannot spot a repeating size. Nothing is sent to UBI's order routes.
Typical usage example:
.venv/bin/python examples/orders/plan_parts/iceberg_execution/iceberg_execution/hidden_size_below_the_market.py
"""
import json
from tradingmachine.assets import equities
from tradingmachine.orders.plan_parts import fixed_pricing
from tradingmachine.orders.plan_parts import iceberg_execution
from tradingmachine.orders.plan_parts import order_part
class HiddenSizeBelowTheMarket:
"""Two icebergs for Vodafone Idea, one regular and one randomised.
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 both orders' objects.
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}")
tick_size = 0.01
if self.share.tick_size is not None:
tick_size = float(self.share.tick_size)
limit_price = round(last_price - 2 * tick_size, 2)
executions = {
"200 at a time": iceberg_execution.IcebergExecution(
visible_quantity=200,
),
"about 200 at a time, varied by up to 25%": iceberg_execution.IcebergExecution(
visible_quantity=200,
randomise_percent=25,
),
}
print(f"Last price of {self.share.symbol}: {last_price}")
for description, execution in executions.items():
part = order_part.OrderPart(
instrument=self.share,
transaction_type="buy",
quantity=2000,
product="cnc",
pricing=fixed_pricing.FixedPricing(
price=limit_price,
order_type="LIMIT",
),
execution=execution,
)
print(f"An iceberg showing {description}:")
print(json.dumps(part.document(), indent=2))
if __name__ == "__main__":
HiddenSizeBelowTheMarket().run()
Build a large buy of Vodafone Idea sent as TWAP slices, each shown as an iceberg¶
Run it with .venv/bin/python examples/orders/plan_parts/iceberg_execution/iceberg_execution/twap_slices_shown_as_icebergs.py.
"""Build a large buy of Vodafone Idea sent as TWAP slices, each shown as an iceberg.
The program reads Vodafone Idea's last price and builds an order for 6000 shares, limited one percent above that price, sent as six TWAP slices over an hour with each slice of 1000 shown 250 at a time and varied by up to a tenth. This is a nested execution: the `TwapExecution` passed as `execution` splits the order into slices, and the `IcebergExecution` passed as `inner_execution` works each slice. Nothing is sent to UBI's order routes.
Typical usage example:
.venv/bin/python examples/orders/plan_parts/iceberg_execution/iceberg_execution/twap_slices_shown_as_icebergs.py
"""
import json
from tradingmachine.assets import equities
from tradingmachine.orders.plan_parts import fixed_pricing
from tradingmachine.orders.plan_parts import iceberg_execution
from tradingmachine.orders.plan_parts import order_part
from tradingmachine.orders.plan_parts import twap_execution
class TwapOfIcebergs:
"""A buy of Vodafone Idea worked as TWAP slices, each slice an iceberg.
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 order's 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)
part = order_part.OrderPart(
instrument=self.share,
transaction_type="buy",
quantity=6000,
product="cnc",
pricing=fixed_pricing.FixedPricing(
price=limit_price,
order_type="LIMIT",
),
execution=twap_execution.TwapExecution(
slices=6,
over_minutes=60,
),
inner_execution=iceberg_execution.IcebergExecution(
visible_quantity=250,
randomise_percent=10,
),
)
print(f"Last price of {self.share.symbol}: {last_price}")
print(json.dumps(part.document(), indent=2))
if __name__ == "__main__":
TwapOfIcebergs().run()