Coder Social home page Coder Social logo

Comments (17)

polakowo avatar polakowo commented on July 27, 2024 1

I knew that such confusion would be coming. If you take a look at the documentation, there are two types of events in vectorbt: trades and positions. Positions have information on two types of events: when you entered the position and when you closed it. If you plot positions with portfolio.positions.plot() of the second column you will see that there is only one position, as you expected. Trades are more fine-grained: each trade corresponds to a sell operation. So, if you decreased your position gradually, it will display lots of small trades, such that you can analyze how good your exit strategy is. That’s why second plot shows you two trades. Both trades have opening index at the same time because their opening price is a size-weighted average over all purchase prices before them (within a position), so their opening index is always the opening index of the position. I will later introduce an example in the docs to make it more intuitive.

from vectorbt.

polakowo avatar polakowo commented on July 27, 2024

There is definitely something going wrong here, but I cannot debug it because I’m on trip and not near my computer. What you can do is do print(portfolio.xs((2, 3, 'BTC'), axis=1).orders.records) and see where vectorbt placed orders. Plots like this mean the position hasn’t been closed, such that first buy is still an opening price for the sell orders to follow until the position is closed (when inside position, each sell takes average price of all previous buys and its opening index is the opening index of the current position). The percentage is applied on the same tick. I will try running this example today using Colab.

from vectorbt.

polakowo avatar polakowo commented on July 27, 2024

Okay, after a bit of debugging with my phone I found where the bug is coming from: this line has to be removed:

if order.size != 0.:
. For now, you can replace your size of 0 with -np.inf and it should work fine. If you want you can remove that line, increment the package version and make a pull request. Otherwise I can only upload the fix after Friday.

from vectorbt.

kmcentush avatar kmcentush commented on July 27, 2024

Just submit a PR. Let me know if I should change anything else. Thanks for looking into this!

from vectorbt.

polakowo avatar polakowo commented on July 27, 2024

Thank you! The fix is now on PyPi.

Has this resolved your issue? Does the column (2, 3, ‘BTC’) now create two positions?

from vectorbt.

kmcentush avatar kmcentush commented on July 27, 2024

Looks like it fixed the issue for (2, 3, 'BTC'), yes. However, the (2, 3, 'ETH') plot is still a little funky in that all positions are the start date because no position was every fully closed. I'm also not sure why it has two entry points despite there being three instances where larger positions are taken. In any case, I'm still not sure what the best way to display incremental position changes would be...

image
image

from vectorbt.

polakowo avatar polakowo commented on July 27, 2024

I’m still not sure what the best way of plotting trades and positions would be, as I couldn’t find anything similar in any backtesting framework.

Edit: if you want a more basic plot such as displaying buy/sell markers, you can do portfolio.orders.plot(), and then portfolio.trades.pnl.to_mattix().vbt.scatter() to plot P&L of your trades.

from vectorbt.

kmcentush avatar kmcentush commented on July 27, 2024

from vectorbt.

polakowo avatar polakowo commented on July 27, 2024

It’s not a bug. Similar to positions, trades can also be open. If at the last tick the position is still open, it will calculate a trade needed to close the position. Bit since at this last tick you have another trade that still doesn’t close the position, you have two trades pointing at the same tick. This is also pointed out in the docs - you can’t transform records to matrix then if you have conflicts like that. What you can do is to choose which kind of trades to use: portfolio.trades.open or portfolio.trades.closed.

from vectorbt.

kmcentush avatar kmcentush commented on July 27, 2024

from vectorbt.

polakowo avatar polakowo commented on July 27, 2024

Portfolio stats reflect both open and closed trades, because reducing operations are applied on records in a map-reduce manner without conversion to matrix form, thus they don’t care about position conflicts. This was actually the reason why I moved from matrix to record representation of event data, because this way we can store multiple elements under the same tick. This will also allow us in future versions of vectorbt to make multiple orders per tick.

Generally, if you look how records were implemented, you will see that some attributes return filtered records. Take for example positions: operations on portfolio.positions will take into account all positions, portfolio.positions.closed only closed, portfolio.positions.closed.winning only closed positions with positive P&L, etc. You can even define your own filters. Portfolio returns stats on trades/positions without any filters, thus on all events.

from vectorbt.

kmcentush avatar kmcentush commented on July 27, 2024

I see. The logic makes sense, especially considering the future when you can have multiple orders in the same tick. However, could it seemingly be dangerous to include open positions in portfolio stats? There's no guarantee that an order will go through on a future date, so it could skew the results. In my case, the open order will have a return of 18% or something. That's not insignificant.

Do other backtesting libraries do similar things in terms of portfolio statistics w/ both open and closed positions?

The filtering of records makes sense, thanks.

from vectorbt.

polakowo avatar polakowo commented on July 27, 2024

That’s a good argument, I never thought about that in depth. The reason why I added this is because if you buy and hold you will still be able to see this position in stats, otherwise all will be NaN. What can be done is adding a keyword argument when initializing portfolio, let’s say ‘unrealized_stats’, that when True will include open positions, otherwise only closed. This can be False by default. But this won’t affect the design of records, ‘portfolio.positions’ and ‘portfolio.trades’ must still return both open and closed events, since when plotting them user must see that his position might not be closed. Maybe we can include an additional warning in docs that records without filters may return unrealized metrics and user must explicitly query ‘closed’ attribute to exclude them.

from vectorbt.

kmcentush avatar kmcentush commented on July 27, 2024

I think it would be good to include a toggle for the portfolio statistics to include unrealized as you said. Or at the very least, enable a way to calculate them efficiently on any filtered trades object (or however you normally do it).

from vectorbt.

polakowo avatar polakowo commented on July 27, 2024

Added the toggle in 0.13.4.

from vectorbt.

polakowo avatar polakowo commented on July 27, 2024

I have looked at the implementation in other backtesting libs, and it seems most of them return statistics of the closed trades only (as you suggested) but calculate unrealized metrics the same way as vectorbt does: using the price at the last tick and without any commissions and slippages applied (thus shouldn't be used in stats, only for information purposes). Thus having the toggle is the most appropriate solution.

from vectorbt.

kmcentush avatar kmcentush commented on July 27, 2024

The implementation looks good to me, especially defaulting to realized-only statistics.

I'm closing this issue for now, I believe you've adequately addressed any issues with plotting multiple orders/explained why things are the case and alternative ways to view the equivalent information.

from vectorbt.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.