How to calculate open position cost basis?
-
Can anybody suggest how to do it? As only current price and size attributes present in Position object I'm assuming I need to calculate cost basis when orders are filled. Is there any code examples how to do it?
-
Cost basis is managed by the
CommissionInfo
objects which live in the broker.If you add/set nothing, then you will have a
stocklike
defaultCommissionInfo
.You can get to the object with (from a
Strategy
instance for example)comminfo = self.broker.getcommissioninfo(data)
The broker reference is here: Docs - Broker
The
CommissionInfo
family is documented here:- https://www.backtrader.com/docu/commission-schemes/commission-schemes.html
- https://www.backtrader.com/docu/extending-commissions/commission-schemes-extended.html
- https://www.backtrader.com/docu/user-defined-commissions/commission-schemes-subclassing.html
- https://www.backtrader.com/docu/commission-credit.html
The actual method to get the cost of an operation is
getoperationcost(size, price)
, which always returns an absolute (i.e.: positive) value. -
@backtrader said in How to calculate open position cost basis?:
The actual method to get the cost of an operation is getoperationcost(size, price), which always returns an absolute (i.e.: positive) value.
I think I'm missing something fundamental here. For getoperationcost to return cost basis I need to pass entry price to it, right? Position object has only current price as far as I understood.
Where can I get average entry price for the position then? Should I calculate it when order is filled?
-
I think you can get it from the trades using
strategy.notify_trade()
or from the orders usingstrategy.notify_order()
. Get prices, store them separately and do the math.For trades you may check
.justopened
event and gettrade.price
(https://www.backtrader.com/docu/trade.html)For orders you might check
order.complete
and getorder.executed.price
(https://www.backtrader.com/docu/order.html)Also if you check
position.price
just after the order is executed, then this price may help. -
@ab_trader thanks. That's what I was afraid of :) See my first message. I was hoping to get cost basis automagically, something similar to this: Position object
-
@Ed-Bartosh it can be a good point for further improvement. If you can offer the approach on how to implement it in the existing framework, then it'll help to community.
-
@Ed-Bartosh quoting from the link:
cost_basis
Float: The volume-weighted average price paid (price and commission) per share in this position.The question here is if the
volume-weighted average price
is actually the cost of entering the position.Putting aside that philosophical detail, there is real problem with the definition:
- A position per se doesn't have any associated
commission
costs
Of course you may argue that if you open a position it has taken money from you in the form of value to enter and the commission for the broker. But you may exit the on-line application of your broker, you log in again and the position is just a position and has no associated
commission
As pointed out by @ab_trader, the actual cost is given you by the
Trades
. - A position per se doesn't have any associated
-
@backtrader said in How to calculate open position cost basis?:
Of course you may argue that if you open a position it has taken money from you in the form of value to enter and the commission for the broker. But you may exit the on-line application of your broker, you log in again and the position is just a position and has no associated commission
I'm not sure I'm getting your point here. Even if I re-login to the broker application I'm able to see position cost basis or average cost if you prefer. It's also available through the API, e.g. by updatePortfolio() call of IB API.
-
But not all brokers are created equal and the goal of backtrader was to be as generic as possible, whilst at the same time providing as much as possible.
Even if someone has created an API/data structure that mimics a specific data strcuture/method of a broker's API, that doesn't make it an standard.
One other reason why in the design of
Position
, the inclusion of commissions wasn't considered:- Multi-Strategy approach
You can have 2 or more strategies which for whatever the reason operate on the same asset. The position is general for all strategies, to let them know what the overall status is, but the commissions are notified individually to the strategies by means of
Order
notifications andTrade
notifications. If the commissions were all inserted in the position, all strategies would understand that the entire amount belongs to the operations they have executed, this not being the case.Most of what Interactive Brokers gives you in a Position is in the
Trade
. Namely:status
(int
): Trade statusdt
(float
): float coded datetimebarlen
(int
): number of bars the trade has been activesize
(int
): current size of the Tradeprice
(float
): current price of the Tradevalue
(float
): current monetary value of the Tradepnl
(float
): current profit and loss of the Tradepnlcomm
(float
): current profit and loss minus commission
-
@backtrader said in How to calculate open position cost basis?:
If the commissions were all inserted in the position, all strategies would understand that the entire amount belongs to the operations they have executed, this not being the case.
Why would all strategies understand that if position is by design shared between strategies? This is actually good thing as position doesn't belong to the strategy, but to the portfolio from my point of view.
Correct me if I'm wrong but as far as I understood you're saying that position cost basis or average position cost is something that's not generic?
IB(and other brokers too, I believe) shows average position cost and doesn't care of how many strategies I used to build this position. Why for it's so different for backtester?
Please, don't get me wrong. I'm not criticising backtester design. The work you've done is exceptional and I'm very impressed by the design and current implementation. I'm just trying to understand it better.
-
Most of what Interactive Brokers gives you in a Position is in the Trade
This is just not true. It shows me average position cost including commissions. It's recalculated after each fill.
-
Looking more carefully thru
position.py
I found out thatposition.price
is a size-weighted average price for current position, calculated considering position changes. Which is a cost-basis, am I correct?Based on docs I thought that it is a price of position based on last asset price.
-
@ab_trader thank you very much! I was also confused by the docs and then by this thread. position.price is what i was looking for.
-
I think I was too quick on this. position.price is not exactly cost basis as it's calculated without using commission. I set commission to 0, that's why the value was the same.
With this code in notify_order:
def notify_order(self, order): if order.status == order.Completed: print self.getposition(order.data).price, (abs(order.executed.value) + order.executed.comm) / abs(order.executed.size)
I've got this output:
106.68 107.7468
I'm not entirely sure, but shouldn't the cost basis and position.price be negative for the short position?
-
@Ed-Bartosh Size is negative. Price is positive.
-
@ab_trader true. anyway it's not what I'm looking for as commission is not included into calculation.
-
To calculate the open position cost basis, sum the total cost of all shares or assets purchased in that position, including commissions and fees.