Closed scoriiu closed 3 years ago
Yes, I think this is necessary.
We need to start moving the account towards something more general, it's currently working for FXCM only.
Probably the AccountState
event needs overhauling, again lets look into the CCXT account updates.
Account update will differ a lot based on the trading type (e.g. derivatives, margin, spot). CCXT doesn't yet take into account these types and returns a poor format IMO. I propose to better look on a account updates via websocket for this types and start from there.
Example bitmex:
{
"table": "margin",
"action": "partial",
"keys": [
"account"
],
"types": {
"account": "long",
"currency": "symbol",
"riskLimit": "long",
"prevState": "symbol",
"state": "symbol",
"action": "symbol",
"amount": "long",
"pendingCredit": "long",
"pendingDebit": "long",
"confirmedDebit": "long",
"prevRealisedPnl": "long",
"prevUnrealisedPnl": "long",
"grossComm": "long",
"grossOpenCost": "long",
"grossOpenPremium": "long",
"grossExecCost": "long",
"grossMarkValue": "long",
"riskValue": "long",
"taxableMargin": "long",
"initMargin": "long",
"maintMargin": "long",
"sessionMargin": "long",
"targetExcessMargin": "long",
"varMargin": "long",
"realisedPnl": "long",
"unrealisedPnl": "long",
"indicativeTax": "long",
"unrealisedProfit": "long",
"syntheticMargin": "long",
"walletBalance": "long",
"marginBalance": "long",
"marginBalancePcnt": "float",
"marginLeverage": "float",
"marginUsedPcnt": "float",
"excessMargin": "long",
"excessMarginPcnt": "float",
"availableMargin": "long",
"withdrawableMargin": "long",
"timestamp": "timestamp",
"grossLastValue": "long",
"commission": "float"
},
"foreignKeys": {
},
"attributes": {
"account": "sorted"
},
"filter": {
"account": 1513111
},
"data": [
{
"account": 1513111,
"currency": "XBt",
"riskLimit": 1000000000000,
"prevState": "",
"state": "",
"action": "",
"amount": 9760950,
"pendingCredit": 0,
"pendingDebit": 0,
"confirmedDebit": 0,
"prevRealisedPnl": 224002,
"prevUnrealisedPnl": 0,
"grossComm": 0,
"grossOpenCost": 0,
"grossOpenPremium": 0,
"grossExecCost": 0,
"grossMarkValue": 0,
"riskValue": 0,
"taxableMargin": 0,
"initMargin": 0,
"maintMargin": 0,
"sessionMargin": 0,
"targetExcessMargin": 0,
"varMargin": 0,
"realisedPnl": 0,
"unrealisedPnl": 0,
"indicativeTax": 0,
"unrealisedProfit": 0,
"syntheticMargin": null,
"walletBalance": 9760950,
"marginBalance": 9760950,
"marginBalancePcnt": 1,
"marginLeverage": 0,
"marginUsedPcnt": 0,
"excessMargin": 9760950,
"excessMarginPcnt": 1,
"availableMargin": 9760950,
"withdrawableMargin": 9760950,
"timestamp": "2020-07-11T12:15:15.470Z",
"grossLastValue": 0,
"commission": null
}
]
}
Also, giving the option to simulate with leverage would be very useful, but this should be a separate thread.
Agreed. Opened an issue for simulating margin and leverage #57.
So I think we should start as simple as possible to achieve some basic functionality and extend from there. I think using BitMEX as a template is a good starting point although I'll also be referring to Binance and other API's. Definitely not every field has to be included or is even available everywhere.
For the current AccountState
event I think the following properties are redundant and/or can be tracked elsewhere.
cash_start_day
cash_activity_day
margin_ratio
margin_call_status
We have to decide a sensible amount of margin information reporting, so it can be both simulated in a backtest, and considered for risk controls in live trading.
I agree. Starting with the basics is a good idea. For the first phase I would propose to ignore the margin related information and have some basic properties like cash
and equity
.
Once the position id issue is fixed I'll refactor Account
to constantly calculate the available equity.
I'll have a closer look at account fields being returned from other APIs and generalize the AccountState
event.
It may take us a few goes to get to where we need to though.
Sounds great!
You could have a go at refactoring Account
so that equity becomes a readonly property in the account.pxd, which is updated every time there's an account state event.
Then that method will be redundant, there's only a few call sites to equity in the codebase I think.
Up to you?
From reading the BitMEX docs today I think there's going to be a growing assortment of metrics being tracked in account.
Shouldn't it be updated on each tick? This is because the unrealized PNL changes from tick to tick. So the account.equity would then be account.available_balance + position.quantity (unlevereged when leverage will be supported ) + position.unrealized_pnl
Bitmex represents wallet with 3 properties: wallet_balance = deposits - withdrawals + realized_pnl margin_balance = wallet_balance + unrealized_pnl available_balance = margin_balance - order.margin - position.margin
I suggest using the same format and drop cash_balance
, cash_start_day
, cash_activity_day
, free_equity
.
Shouldn't it be updated on each tick? This is because the unrealized PNL changes from tick to tick. So the account.equity would then be
account.available_balance + position.quantity (unlevereged when leverage will be supported ) + position.unrealized_pnl
You're right Account
will need to receive QuoteTick
s for any assets its holding so that unrealized data can be generated. I can just add a simple handler method, and automatically send relevant quote ticks to it from the DataEngine
before any strategies. I'm still getting my head around how BitMEX handles the leveraging so it may need other data such as Mark
and Fair
price, unsure at the moment.
I suggest for the first phase going with the simplest leveraging mechanics operating based on the QuoteTick pricing info and a leverage variable. Also having a warning in the code if leverage is configured, saying that liquidation functionality is not yet available. Later we can add more complex logic for liquidations operating based on the Mark and Index pricing info.
I've been thinking about how to set this up and it may be cleaner and more appropriate to have the Portfolio
provide the realized and unrealized PNL as it holds a reference to all of the positions (which in turn provide their own PNLs). It would work in conjunction with Account
to determine available equity and margins.
It could even subscribe to and unsubscribe from the quote ticks it requires to calculate unrealized PNL based on which symbol positions are currently open. I'll do some more thinking and see what comes out when I start coding it.
Regarding the leverage I agree a simple property with a warning if set above 1, we can mature the feature as live trading capability gets closer.
I also note the need to track order margin.
Sounds good. I haven't really looked into the Portfolio logic yet. So will both Account and Portfolio track the total margin of the account then? Who will in this case track the available balance (which is wallet_balance - position_margin - working_orders_margin)?
Account
and AccountState
have now been stripped back in preparation for the redesign.
I'm flagging that whilst BitMEX is being heavily referenced as a model, the platform must remain as general as possible to continue working for other exchanges/brokers and asset classes.
The AccountInquiry
command has been removed for simplicity (was an artifact from FIX4.4
and applicable there only). The user/system should not be responsible for manually requesting account information, this will be handled inside individual connected ExecutionClient
s, ensuring that Account
states are always consistent and up to date.
Portfolio
has been stripped back and wired into the system more effectively - ready for the new design. Account
s are now registered with the Portfolio
as they come online which will help with all kinds of PNL and margin calculations depending on where we decide the responsibility lies.
This thread seems to be converging with #57
Account should reflect the equity balance at all times. In case there is a position open, account.equity should be something like
cash + position_value_unleveraged + unrealized_pnl