- ago
I have it set to 0 commission. No margin interest. Fixed position size of 5k. Cash of 1B. No slippage.

The Profit calculation is off in all 3 trades. Higher in the first and lower for the next 2. The third one is way off (88c)

Is anyone else experiencing this?

What other setting could possibly be causing this?

Thanks

0
1,025
12 Replies

Reply

Bookmark

Sort
- ago
#1
FYI, it's pretty much off on every trade but I picked these three because they were in a row, has 1 small up, 1 small down and a big down compared to the correct value.
0
- ago
#2
Reason: Display rounding

Here, WL7 rounds the entry and exit prices to 2 decimals on the Positions tab while processing them with full precision internally.

For example:

- WL7 shows you an exit price of 412.86 and an entry price of 385.07. The difference is 27.79 and for 1035 shares you think you should get a profit of 28762.65.
- Internally, the prices are represented as 412.859985 and 385.0687... so the real displayed profit is 28763.89...
0
- ago
#3
Ok, I figured it was a rounding error given that the settings looked correct but stock prices and position sizes are not full precision if there are no splits involved and WL6 didn't do this. There were not any splits from the start time to current for the first and third stocks and the second had one after that trade.

I ran the test again with Yahoo data rather than WL Data since Yahoo data is only 2 digits. The same error occurred.

The precision error on profit over a single simulation I ran over a year was 13% and it grew exponentially if using non-fixed position sizes or a longer time frame since the positions grew in size.

IMO this is non-trivial.

Thanks
0
Cone8
 ( 4.83% )
- ago
#5
QUOTE:
WL6 didn't do this
.
Yes it did, but only if you "Turn off limit/stop-order rounding entirely", which I always did because if you don't, a split is likely to change your backtest.

QUOTE:
since Yahoo data is only 2 digits.

It's not 2 digits if any adjustments are applied (splits or dividends)

QUOTE:
The precision error on profit

The error is yours because you're not calculating it correctly - using full precision. Isn't this clear from Eugene's post above?
0
- ago
#6
Ok, so I am going to respectfully, but strongly disagree here and give more information since this is a deeper issue on a couple of levels now that we agree that precision issues could arise with splits and dividends. Let's dive deeper.

Stock 1 is BIIB:
Splits 12/21/99 2:1, 1/18/2001 3:1
No dividends
Trade Dates: 4/24/20 - 4/28/20
Error: + 0.03

Stock 2 is VRTX:
Splits 8/24/20 2:1
No dividends
Trade Dates: 4/28/20 - 4/29/20
Error: - 0.04

Stock 3 is PDD:
No Splits
No Dividends
Trade Dates: 4/28/20 - 4/29/20
Error: - 0.88

Here are the issues that make this a bug (switching the order around):

1) PDD - no splits - no dividends so there should be NO precision issues. This one is off by the most!

2) BIIB - no splits after the trade period. There should be NO precision issues.

3) PDD - split after the trade period but no splits DURING the trade period. There should be NO precision errors.

Let's look at why the first 2 situations are definite bugs and the 3rd is still a bug but a "possible" philosophical disagreement but one that hopefully you will think seriously about and consider fixing if it's not done this way already even if it's a big change.

Keep in mind about how one actually trades in the market while thinking about this. I.e. the markets don't trade with full precision but for all practical purposes (especially with daily data) they only trade with 2 decimal point precision.

1) PDD: There is no justification for a precision error here - therefore BUG.

2) BIIB: When adjusting for splits - traditionally e.g. on Yahoo Finance, adjustments are made BACKWARDS. I.e. no adjustments to stock prices are made after the last split and adjustments are made pre-split. So for BIIB, since the last split was in 2001 and the trade happened in 2020, there should be no adjustments during the trading period so there is no justification for a precision error here - therefore BUG.

3) PDD: This one is kind of arguable but not really IMO. Here a split happened AFTER the trading period. So if trading this live, the split would NOT effect the trade in any way shape or form. I.e. if no splits or dividends happen during a trade then only the UNADJUSTED values matter. Why? Aren't the values going to be the same if you use split adjusted values throughout the trade if they are adjusted for a split after the trade?

NOT ALWAYS because, as we all know, computers have precision point errors when dividing. So how should it work IMO? Adjustments should only be made to the raw values IF a dividend or split happens DURING a trade. I understand that this could be a fundamental change and a lot of work and it may not seem significant but it truly is when backtesting 100s of stocks over 20+ years using fixed, or even more so % of capital, position sizes.

So this may be intentional but it still obviously causing errors in the Profit Values, even though it's only a 2:1 split without dividends, so therefore BUG.

Please look at this a lot closer and don't just write it off to display rounding.

Thanks
0
Cone8
 ( 4.83% )
- ago
#7
The issue is the precision of trade execution price.  You can adjust your code to fix that.  Maybe WL7 can add an option to help too - we'll see what makes sense.  Either way, there's no easy one-fits-all solution here.  Let's add context here -

Background...

Version 6, by default rounded stock prices to the nearest penny (and futures to their tick price, etc.) That's a problem for stocks in backtesting when dealing with prices that have been split or otherwise adjusted.

The way to get around that in Version 6 was to turn off stop/limit rounding.

Furthermore, stocks routinely trade at higher precision than 0.01.  You'll see executions at 0.001 increments on your broker statements.  OTC stocks trade at 0.0001 increments.  Also, depending on the world exchange, more precision is required.  ASX stocks below 10 cents trade at 0.001, and below $2 at 0.005.  Just some of many examples.

So, what's the solution for all world users of Wealth-Lab?  That's the question we have to answer.   I can think of the solution for you today - adjust your limit and stop prices so that they fall precisely where you want them.
0
Cone8
 ( 4.83% )
- ago
#9
I mocked up a solution that could be the beginning of something WL7 does later. Assuming a 0.01 tick price now, it uses the SplitReverse Indicator to determine the tick price in the past, adjusted for splits.

You can use the pattern shown in this code to fix the issue right now in $1B simulations.

CODE:
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Indicators; using System.Drawing; using System.Collections.Generic; namespace WealthScript4 { public class MyStrategy : UserStrategyBase { public override void Initialize(BarHistory bars) {                   TimeSeries sr = bars.Close / SplitReverse.Series(bars, PriceComponents.Close);          _tick = new TimeSeries(bars.DateTimes, 0.01) * sr;          _sma = SMA.Series(bars.Close, 20); } public override void Execute(BarHistory bars, int idx) {          double limit = _sma[idx];          limit = FixPrice(idx, limit);          WriteToDebugLog(bars.DateTimes[idx].ToShortDateString() + "\t" + limit.ToString("0.00######") );           }       TimeSeries _tick;       SMA _sma;       double FixPrice(int bar, double orderPrice)       {          return Math.Round(orderPrice / _tick[bar]) * _tick[bar];       } } }


The example uses a SMA to act as a limit price that's rounded to the tick price. If you run this on QLD, for example, you'll see the precision of the orders change before the 8/18/2021 2:1 split :

CODE:
8/12/2020   84.265 8/13/2020   84.675 8/14/2020   85.065 8/17/2020   85.32 8/18/2020   85.755 8/19/2020   86.10 8/20/2020   86.79 8/21/2020   87.62


And again before the 7/17/2017 2:1 split:

CODE:
7/13/2017   29.5025 7/14/2017   29.5675 7/17/2017   29.6475 7/18/2017   29.70 7/19/2017   29.775 7/20/2017   29.845 7/21/2017   29.915


But rounding isn't really the right way to do it. Buy Limit orders need to be Floored and Short Limit orders need to be Ceiling'd (if that's a word). Anyway, rounding is certainly close enough, well, unless you have a billion dollars, which we might all have pretty soon if the FOMC has it's way!
1
- ago
#10
Ok, so the rounding on the buy/sell orders seems to be the main issue then like you suggested. I have to assume the quantity is an integer since I'm not sure how to check this.

Personally, given that stock brokers don't allow placing orders with more than 2 decimal point accuracy, I'd make it so that all orders default to that (via rounding/flooring/ceiling/whatever).

It's really a pain to have to put Math.Round(price, 2) or use the FixPrice function for every single order in every single strategy. Please consider doing that as it would make the profit calculations more accurate for the majority of clients.

Thank you for your explanations.
0
Glitch8
 ( 11.08% )
- ago
#11
Orders sent to brokers do use the rounded values.

Quantity is a double since many brokers accept fractional shares and it's especially important for cryptos and even mutual funds.
0
- ago
#12
Thanks but that's even worse because the rounded order values are not being used in the backtesting so they aren't reflecting what would happen when placed.
0

Reply

Bookmark

Sort