Coder Social home page Coder Social logo

Comments (8)

edtechre avatar edtechre commented on May 22, 2024 1

The calculations there look correct to me and is consistent with my explanation of calc_target_shares and buy_fill_price above.

ctx.buy_shares = ctx.calc_target_shares(1)

By default, this uses the close price of the last completed bar. It is never the fill price of the next bar, because that would introduce lookahead bias. You can't calculate the number of shares to buy based on a future price you haven't seen yet.

For the first trade, close price = 2647.580078125
100000000 // 2647.580078125 = 37770 shares

Then the actual open price is 2645.100098. The exit price is 2741.060059.
PnL = (2741.060059 - 2645.100098) * 37770 = ~3624408e6

This is consistent with the dataframe before the values are quantized by rounding up to the nearest cent.

from pybroker.

edtechre avatar edtechre commented on May 22, 2024

It seems the execution price when buying is the price of last bar, even "ctx.buy_fill_price = PriceType.OPEN" has been set. Is this intentional?

Yes, this is intentional since calc_target_shares is generic and can be used to calculate buy_shares or sell_shares. You will need to pass in the previous day's open price using self.open[-1] if you intend to use the open price.

from pybroker.

none2003 avatar none2003 commented on May 22, 2024

Hi @edtechre,

Well, my intention is:

I want to buy or sell a security tomorrow at the open price, once I found a calculated signal based on today's close price appears.

For example, on 2023/12/5, I'm backtesting a strategy on a security data from 2008/1/1 to 2008/3/1, now I found close price is cross up MA20 on 2008/1/10, and I want to buy this security at the open price of very next day (2008/1/11).

How would I do that?

And what's the point show the shares/pnl which doesn't match with the entry/exit price in the result.trades?

There is another question:
If I have to pass the self.open[-1] to calc_target_shares manually, what's purpose of the setting in doc: ctx.buy_fill_price = PriceType.OPEN and ctx.buy_fill_price = PriceType.OPEN?

from pybroker.

edtechre avatar edtechre commented on May 22, 2024

Hi @none2003,

Sorry that I did not previously address your concerns. I misunderstood your original posts and it seems there are two different issues here:

The first shares value is 112694 rather than 100000000 / 887.064(entry price) = 112731.

Personally, I think 112731 is right.

And even shares value of 112694 were correct, shouldn't the pnl be 112694 * 1012.578(exit price) - 100000000 = 14111465.13

I believe the discrepancy is due to rounding. My suspicion is that the entry price is not 887.064 but is some some other floating point value. Note that the values in result.trades are rounded up to the nearest cent before they are displayed.

If you can email me your data with the symbols anonymized, I can take a look and verify this.

I want to buy or sell a security tomorrow at the open price, once I found a calculated signal based on today's close price appears.

This is done by setting ctx.buy_fill_price = PriceType.OPEN.

If I have to pass the self.open[-1] to calc_target_shares manually, what's purpose of the setting in doc: ctx.buy_fill_price = PriceType.OPEN and ctx.buy_fill_price = PriceType.OPEN?

They serve different purposes, calc_target_shares is a helper function for calculating the number of shares to buy or sell. Passing in self.open[-1] will calculate the number of shares based on the last completed bar's open price. Setting ctx.buy_fill_price = PriceType.OPEN will set the fill price to the open price of the next bar.

It sounds like you want to calculate the number of shares (i.e. 20% of your portfolio) to a symbol using the next bar's open price. But this is not supported because it would introduce lookahead bias into your strategy, and would likely be unrealistic to implement in a real strategy anyway due to slippage.

from pybroker.

none2003 avatar none2003 commented on May 22, 2024

issue#80.zip

I uploaded an example notebook. This strategy is simple:

  • if no long position and close price > ema_20, then buy ^SPX with all the cash at next bar's open price;
  • if long position exists and close price < ema_20, then sell all the long position at next bar's open price.

The very first buy order is filled with open price 2645.10 of 2017-12-01, this is consistent with the settings (ctx.buy_fill_price = PriceType.OPEN). However, the "shares" number is 37770, I think it should be 100000000 / 2645.10009765625 = 37805.

The following sell order is filled with open price 2741.06 of 2018-02-05, this is also consistent with the settings (ctx.sell_fill_price = PriceType.OPEN). Let's assume share number 37770 were right, the pnl should be 37770 * 2741.06005859375 - 100000000 = 3529838.4131. And if using share number 37805, that will be 37805 * 2741.06005859375 - 100000000 = 3625775.5151. But in result.order, it gives 3624407.72, largely differs with both numbers above given.

from pybroker.

edtechre avatar edtechre commented on May 22, 2024

Thank you for providing a notebook. However, I will need data to be able to debug.

Let's assume share number 37770 were right, the pnl should be 37770 * 2741.06005859375 - 100000000

I am not sure where 100000000 comes from. The PnL is not calculated using your initial cash, it is calculated as the PnL from entry to exit:

entry_amount = shares * entry_price
exit_amount = shares * exit_price
entry_pnl = exit_amount - entry_amount

If config.enable_fractional_shares was not set to true, then not all of your initial cash (100000000) will be invested since only whole shares will be traded.

from pybroker.

none2003 avatar none2003 commented on May 22, 2024

Please download and check the notebook, I used Yfinance to get "^SPX" data live inside notebook, like pyb example notebooks.

from pybroker.

none2003 avatar none2003 commented on May 22, 2024

OK, I see. Thank you for the detailed explanation.

from pybroker.

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.