Placing Trade Orders on Blueshift娦
Orders, trades, positions¶
Fractional trading support.
Blueshift now supports fractional trading, i.e. order quantity need
not be an integer and fractional amount is supported (if supported
by the broker). Some brokers (e.g. Crypto brokers) offer exclusively
fractional trading. For such cases, Blueshift will automatically
treat every order as fractional. For brokers which do not exclusivly
offer fractional trading (e.g. Equity brokers), you must specify a
keyword argument fractional=True
in the ordering API functions to
make it fractional.
On Blueshift®, we interpret the terms order
, trade
and position
in
a certain way. An order
is what is generated by your trading algorithm.
It is an intent to trade. An order, once created by a strategy is sent
to a broker (either the backtesting engine or a real live broker) for
execution. At the broker's end, this order will go through some checks
and will be executed. This leads to some specific buying and selling -
these are what we call trades
. A single order can potentially generate
multiple trades. As an outcome of these trades, your strategy ends up
with certain assets - these are called positions
.
It is natural to track orders
by their order IDs, trades
by their
trade IDs and positions
by their underlying assets.
On Blueshift® we do not always track the trades and support may
not be available for all brokers. Orders
and positions
are the
key metrics by which a strategy keeps itself aware of its exposure.
For more on Order
and Position
, see the
API doc.
Placing orders¶
Trading capacity
Ordering functions will not check the capacity of the account to validate the order (e.g. cash, margin requirements etc.). You must check it yourself before placing any order.
To place an order, strategy needs to specify an asset, and the other
order parameters. The most basic ordering function is order
. It has the
following signature
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Always check if the return value is None
or a valid order id. We return
None
for the following cases
- The order was invalid and was not placed with the broker
- The order type was
market
and resulted in unwinding of existing position(s). This is the case where the broker does not support fungible orders1. In such cases, only an order for the residual amount will be created (if any) and order ID of the same will be returned.
At present only limit and market orders are supported. Stop loss
specification will be ignored. The handling of limit and stop price
specification is totally implementation depended. In case the broker
supports limit orders, limit_price
will be effective. In most current
versions of broker implementation, the stop_price
is ignored.
asset = symbol("AAPL")
order_id = order(asset, 10) # a market order for 10 stocks of Apple Inc.
order_id = order(asset, 10, 208.8) # a limit order at 208.8 or better.
The code snippets above places two orders, one at the market, the other at a limit price.
Order sizing functions¶
While order
is the base function to trade, there are a bunch of other
helper functions that does automatic order sizing. Most quant strategies
will find this more useful than the raw order
functions.
-
order_value(asset, value, limit_price)
: Place order for an asset with a specifc dollar value (instead of quantity). -
order_percent(asset, percent, limit_price)
: Place order for an asset with a specifc precent of current portfolio value. -
order_target(asset, quantity, limit_price)
: Place order for an asset with to target a specific quantity. If the existing amount in portfolio is less than this, buy orders will be generated. If it is more, sell orders will be placed. Else no change. -
order_target_value(asset, value, limit_price)
: Similar to above, but target a particular dollar amount instead of quantity. -
order_target_percent(asset, percent, limit_price)
: For targetting a position worth a specific percent of the portfolio value.
The last function - order_target_percent
- is very useful. It combines
the targetting along with automated sizing based on current portfolio
value.
For more on order placing APIs, refer the API doc.
Automatic order sizing
These order sizing functions will take in to account current position, but not outstanding open orders. Be cautious.
Fetching and canceling open orders¶
To fetch the current open orders (orders still to be executed fully and
are not cancelled/ rejected), use the API function get_open_orders
.
This will return a dict
(a Python dictionary) with order IDs as the
keys and order
object as the value. To cancel the remaining part of
an open order, use the API function cancel_order
. Example below:
open_orders = get_open_orders()
for order_id in open_orders:
cancel_order(order_id)
In many situations, this code snippet is very useful. Whenever we are rebalancing our portfolio to a particular signal, we usually want to ensure we do not send out duplicate orders for the ones that are already outstanding. We also do not want to leave the open orders as they signals might have changed their veracity. In such cases, it is best to query and cancel all open orders before placing fresh ones.
For more on order management APIs, refer the API doc.
Squaring off
For live brokers, in most cases, we support a square_off
function
that will send exit request for all positions, after cancelling
all open orders.
-
This means issuing a buy and sell order of same amount on the same asset does not create a null positions, but two different positions, with potentially margins blocked for both. For such type of accounts, Blueshift® will first try to see if a new order can be filled by unwinding existing positions. An order for the remaining amount, if any, will be sent. This is only valid
market
orders. ↩