Continuing the strategy port sub-series, we will now design the trading port.
In the modules and components post, we defined the trading port as a gateway to exchanges, managing a trading account, placing and canceling orders.
We will do as we did for the market port, that is, start with describing the domain model then proceed to defining the features supporting this representation of the world.
A trading account is a financial account maintained by an exchange or broker, that represents the funds they hold on behalf of the customer. The customer can use those to trade directly, or in the case of more sophisticated instruments, as a collateral securing repayment of leveraged positions.
As such, it has a more complex working than the usual deposit account. We shall use the following definitions, relevant to our trading project using accounts that support trading on margin:
- Asset balances
The amount of each commodity and security owned by the customer. Barring blocked funds used as collateral, those are the amounts available for withdrawal.
- Margin balance
The total value usable as a collateral for margin positions. It might differ from the total counter-value of asset balances, because not all assets might be usable as a collateral.
- Open positions
On-going trades, where the asset was successfully sold (for short positions) or bought (for long positions) but not yet bought/sold back.
- Used margin
Total counter-value currently blocked as a collateral to open positions.
Current counter-value of the account. That is, the total counter-value of asset balances plus/minus any unrealized profits/losses from open positions.
- Margin level
Ratio of equity to used margin. This gives a measure of how exposed the account currently is to markets. When this number goes below a certain exchange-specific threshold, it will start forcefully closing loosing positions (a process known as liquidation).
In addition, an account is associated a list of orders, and a ledger that keeps track of all fund movements for legal and fiscal proceedings.
Anatomy of an order
Apart from deposits and withdrawals, which Cryptomate does not care about, all changes on a trading account are the results of executing orders.
Each order represents the intent of the account owner to buy or sell an asset for another. They come in two types:
- A limit order has a fixed price, representing the worst price the owner wants to trade at. That is, highest price he wants to buy at, or lowest price he wants to sell at. Such an order goes to the order book if it has no counterparty when it is opened.
- A market order has no fixed price, it requests an immediate trade, at whatever the best prices currently are.
In addition to their type, orders have a
side (buy or sell), total
volume to trade,
expiration date and for margin trading, the
leverage to use.
Once issued, the order follows the following life-cycle:
Market orders follow the same state diagram, except they are executed instantly at the best possible value. This leaves no opportunity for cancelling or expiration, and it only remains if partially filled state while it is being processed.
During its life, an order will generate trades. Possibly zero if it gets cancelled, possibly many if it gets matched to a several smaller orders. The exact list of trades is usually of little value, but some aggregated statistics are commonly used, most notably:
|How much was bought/sold so far.
Equals total volume on a closed order.
|How much was spent to buy/sell so far.
|Cost / executed volume.
|Total amount of fees paid for the trade so far.
Ever heard trading is a zero-sum game? Well, not so much.
|Time at which the order was cancelled.
|Time at which the order got fully filled.
Lastly, it is a common practice to match orders on the same market into positions. This logical grouping makes it possible to easily think about a position in terms of running profits and losses. As this grouping as actually related to a specific way of thinking about the strategy, it will not be handled at the trading port level.
Trading port features
As previously established, the purpose of the trading port is to abstract out all the details of connecting to a trading account and using it. That is:
- Querying its status.
- Placing and cancelling orders.
- Subscribing to real-time events that affect account's orders.
Seen from client code, the trading port is straightforward:
- Hand an account description to the trading engine.
- Get an
- Use it to query its state, place or cancel orders.
- Get notified of every order-related events through a callback.
- Close the
Accountobject when no longer needed.
Assembling the features and objects described in previous sections, here is the full list of interfaces that, together, constitute the trading port:
|A valid, opened account on a trading platform.
|Static data granting access to a trading account.
|Callable that responds to events happening on an account.
|Main port entry point.
|Relevant trading rules for an
|A single trade resulting from an order.
For detailed specification of each interface, check their definition and inline documentation on GitHub. Again, due to the dynamic nature of python, not all interfaces need to appear as python types within the code.
That is it for the trading port. You will find the result on GitHub under the
directory. In the next post, we will turn to the remaining ports
of the strategy evaluator, which should be simpler.