Quick update from me - not much happening, so I'm doing some refactoring of my backtest plumbing. I want to be able to run a fully realistic backtest of the system, which as of few months uses Rob's DO magic. By realistic, I mean exactly as it's running in production, including running all the risk measures, position sizing and DO logic for every day. I got it working just now, and the first backtest results are below. Obviously, now I gotta go dig for the bug that I have...
I'm able to do that with my system, i.e. I can simply pump individual historical EOD prices through it as if it were RT-prices and it behaves exactly the same as it would with actual prices (the execution layer gets replaced of course..). The problem with that is it's still not as realistic as Rob's backtesting system because mine would by definition use the same set of parameters for the whole period (instrument\signal weights etc.) which were chosen by looking at the whole history (i.e. using a "time machine")., and Rob's is continuously reoptimizing everything using only data available up to the that point. Also uneven amount of historical data for different instruments makes it unrealistic because my weights are static so in the beginning the system is able to use only a fraction of capital until data for all instruments becomes available.. But it is still useful at least for testing and to see that overall it does what it supposed to do and would make some money..
The bug up there was interesting - I was fetching the prices used as fill prices in the wrong order. If you ever wondered what the backtest looks like if you could be filled on yesterdays open price (as opposed to tomorrows), that's that I do have another question - I've been running DO for just over 2 months now and am seeing quite a lot of position flips. Here's an example from the backtest: Code: 2021-04-16: 2022-05-24 09:29:58 {'type': ''} Tracking error of current positions vs unrounded optimal is 0.0493 larger than buffer 0.0125 2022-05-24 09:29:58 {'type': ''} Optimised (before adjustment) weights, tracking error vs unrounded optimal 0.0554 costs 0.0015 2022-05-24 09:29:58 {'type': ''} Tracking error current vs optimised 0.0296 vs buffer 0.0125 doing 0.578 of adjusting trades (0 means no trade) 2022-05-24 09:29:58 {'type': ''} Optimised (after adjustment) weights, tracking error vs unrounded optimal 0.0554 costs 0.0015 Processing 2021-04-16 with capital 600000.0 with 8 trades [2021-04-16] handling trade MNQ -1. Filled on 2021-04-19 @ 13940.75 [2021-04-16] handling trade EOE 1. Filled on 2021-04-19 @ 695.2 [2021-04-16] handling trade MNTPX -1. Filled on 2021-04-19 @ 1917.0 [2021-04-16] handling trade DJ600 -1. Filled on 2021-04-19 @ 425.7 [2021-04-16] handling trade QG 1. Filled on 2021-04-19 @ 3.0775 [2021-04-16] handling trade MES -1. Filled on 2021-04-19 @ 4137.75 [2021-04-16] handling trade SCI 1. Filled on 2021-04-19 @ 124.95 [2021-04-16] handling trade LE -1. Filled on 2021-04-19 @ 131.975 2021-04-19: 2022-05-24 09:29:58 {'type': ''} Tracking error of current positions vs unrounded optimal is 0.0570 larger than buffer 0.0125 2022-05-24 09:29:58 {'type': ''} Optimised (before adjustment) weights, tracking error vs unrounded optimal 0.0490 costs 0.0013 2022-05-24 09:29:58 {'type': ''} Tracking error current vs optimised 0.0292 vs buffer 0.0125 doing 0.571 of adjusting trades (0 means no trade) 2022-05-24 09:29:58 {'type': ''} Optimised (after adjustment) weights, tracking error vs unrounded optimal 0.0490 costs 0.0013 Processing 2021-04-19 with capital 600000.0 with 10 trades [2021-04-19] handling trade MNQ 1. Filled on 2021-04-20 @ 13849.25 [2021-04-19] handling trade M2K 1. Filled on 2021-04-20 @ 2208.4 [2021-04-19] handling trade EOE -1. Filled on 2021-04-20 @ 689.15 [2021-04-19] handling trade MNTPX 1. Filled on 2021-04-20 @ 1914.0 [2021-04-19] handling trade DJ600 1. Filled on 2021-04-20 @ 424.8 [2021-04-19] handling trade QG 1. Filled on 2021-04-20 @ 3.1125 [2021-04-19] handling trade MGC 2. Filled on 2021-04-20 @ 1781.8 [2021-04-19] handling trade MES 1. Filled on 2021-04-20 @ 4114.25 [2021-04-19] handling trade V2TX -1. Filled on 2021-04-20 @ 22.0 [2021-04-19] handling trade MXP 1. Filled on 2021-04-20 @ 0.04813 This happens *a lot*. These are 2 consecutive days (there's a weekend between them) and there's no fluctuation in the account capital, we're at ATH. Yet, trades for MNQ, EOE (AEX), MNTPX (Topix), DJ600 and MES were reversed the next day. Some of these even have a better optimal position on the latter day (I'm aware DO can still decide to reduce position if it reduces the tracking error). I tried playing with tracking error buffer and it does make it better if I increase it, but at this point it's just overfitting. Using the method to estimate it that Rob described in https://qoppac.blogspot.com/2021/11/mr-greedy-and-tale-of-minimum-tracking.html, I also get 0.0125 (no wonder, I'm running exact same risk params as Rob). Anybody else seeing this? I see some of that in Rob's trade reports, but I'd say not to the extent I see here. I already checked that my cost settings (commissions and slippage) are correct, as that's the one thing that could cause it. Correlation and covariances also look correct.
I do get some position flips, even in the same day because I'm running on ticks: But it doesn't happen every day and in general the number of trades is in line with what I had before DO. And I think of them not as flips but as "well, the situation(prices) changed, so the positions changed accordingly" I did play with the "DOTradeShadowCostAnual" and "DOBufferSizeDailyRiskAnual" parameters, but I also have a 3rd parameter, which is a multiplier for "DOBufferSizeDailyRiskAnual" and it's set to 3., the way it's used is I'll not even attempt to perform optimization unless the difference is below 3xDOBufferSizeDailyRiskAnual. the parameter values are DOTradeShadowCostAnual=30 DOBufferSizeDailyRiskAnual = 0.015 And I remember when I was adjusting them, they didn't match to the Rob's values, so I basically fitted them to make the number of trades as before DO..
actually, this was on my list for some time - to check if I started trading more after implementing DO in reality, because I run my backtest on the daily prices but trade on ticks, so the results might not be the same. So I ran a query now that shows weekly number of filled orders: I put DO to PROD in the beginning of Jan 2022 (I think?), so it does appear the the system started to trade more., the average number of orders per week was around 10, now it's around 20, maybe I should increase "DOBufferSizeDailyRiskAnual" somewhat. But there's no way to even fit it, only trade it live for a while and see.. Maybe I'll do that on my paper system..
In backtest I found that DO traded more often than my original system (turnover in risk terms) but had lower trading costs, due to sticking with cheaper instruments when possible. But it wasn't trading twice as much so that sounds a bit fishy. Something to bear in mind is that DO will probably prefer to trade instruments with smaller risk, hence the number of contracts traded will be a little higher. One thing that makes it difficult to judge is the stochato nature due to the buffering; you can go days without trading and then all of a sudden you do a bunch of trades. For a short evaluation period you can easily get a lot of DO trades if you'r unlucky. I guess ultimately you need to have a hard look at your backtest and check your live trading behaviour is in line with what you expected from that. Basically fit turnover/cost behaviour on the backtest, and then check production comes out in line with that. Here's a picture. It's my cumulative live trading spread costs for the last couple of years or so (basically once I had pysystemtrade running in live) as a % of my capital. I'd be worried if the thick grey line showed a steeper gradient at the end, post DO, but it doesn't. Rob
yes, I definitely see that behavior.. yeah, I need to try to construct another report: cumulative costs as (Ask-Bid)*Qty+Commission at the time of every trade and see what that looks like, because the number of trades might not reflect costs well. But the problem for me is that my backtest is on EOD prices and live trading is on ticks (I perform DO every 10 seconds), so even though my backtest shows an even lower number of orders compared to "non-DO", in the live trading I'll almost certainly get more, e.g. this is from today: These 2 trades wouldn't have happened if I traded only once a day.. My "non-DO" backtest was also using just EOD prices, but maybe DO increases trading more when going from EOD to ticks compared to "non-DO".. I recently tightened my daily trading limits and will probably increase the DO buffer size after constructing another report..
If that isn't a typo, then that seems insanely frequent. (No offense intended...just trying accurately express my reaction to reading that.) I will admit that it's impressive that you can do that. But why would you care about tracking error on that small of a timeframe?
Yeah, I agree that it's a bit crazy in the context of this relatively slow system The thing is that my system was real-time event-driven from the beginning, it's a service that's always on (excluding daily maintenance periods) so it receives every new bid and ask tick, decides the new optimal position and propagates these ticks with the desired position down to the execution layer which might adjust the limit price or place\cancel an order. At first I was even running full DO on every tick, but that turned out to be too much even for my relatively beefy server ., so I introduced an artificial threshold to not do it more often than every 10 sec (all ticks are still propagated to the execution-layer for order management, but the target position isn't always recalculated). For sure such frequency is unnecessary, and like in this case can cause issues with too much trading, but it's too late for me to change the architecture, it's already written this way. (and who knows, maybe I do get some extra-benefits from reacting more quickly )
HWM yesterday, which was nice. Had a slightly weird evening yesterday as part of a conference to retail traders sponsored and organised by a CFD broker. Me and a bunch of weird discretionary people. They all laughed when I told them I had no idea what my positions are, but stopped laughing when I had to check my phone to see if I was short Yen. Got to meet John Bollinger though, nice old gent, so I'm now going to excise any rude comments about Bollinger bands from my book draft. I'm appearing on TTU on Saturday. Any questions reply to this thread or email Neils info@toptradersunplugged.com (by Friday lunchtime if possible) Rob