July 21, 2007
When you are designing a real-time trading system, many things can go wrong. This post is intended to alert you to some of the potential pitfalls. However, that is all it can do. Only experience can teach you how to prevent them. Be aware that even the most experienced designers will make some of these mistakes repeatedly.
Since documenting all potential pitfalls with coding examples would consume too much time and space, they are, for now, only briefly commented on. Most of them will trigger a user response of “Oh yeah, that happened to me!”. If you need a more detailed explanation you can post questions in a comment to this post
No rules exist to prove that a trading system is free from coding or logical errors. However, two indicators are fairly reliable in suggesting you may have a problem:
1) Your profits are simply too good to be true. In this case you have no choice but to work through the code line by line, trying to find lines of code that look into the future. If that doesn’t reveal any errors, then you would have to inspect the plotted signals and trade list trade by trade.
2) Your system is very profitable trading Long but not Short, or Short buy not Long. When this happens, you may have an error in either the Long or Short parts of your code, and comparing the two sections will often reveal the problem (this only works for reversal systems). However, it could also be that your code is correct but that your trading principle is overly trend sensitive. This would almost certainly get you in trouble when the trend reverses. In this case no other cure exists than to re-think the basic system.
When designing high-frequency trading systems, i.e., those whose trade durations are in minutes, everything changes, and many traditional procedures fall apart. Internet delays, data delays, bad data (spikes), temporary system freezes (Windows sometimes has a mind of its own!), lagging status reports, TWS problems, etc., all become critical issues that will prevent you from obtaining a close match with the Backtester.
Many of these problems will only surface when you start trading real money. Hence, the final stages of developing a trading system should always involve trading real money. Here is where the Interactive Brokers account simulator (paper-trading account) may be an indispensable tool since you can test your system in real time without committing real dollars. But, since the market does not see your trades, even paper-trading results will differ from trading real money. In general, the faster you trade, the greater your real-trading results will deviate from your backtest results. You should also be aware that commissions play a much greater role on performance of high-frequency trading systems because trade profits are smaller.
No matter how you go about it, troubleshooting a complex trading system will almost always be a tedious and boring job that could keep you busy for several days or weeks. If you find that certain problems continue to resurface, they are likely related to your personal development style, and you may be able to write some code that checks for these specific problems. See the Debugging category for some ideas.
The list below, which is not exhaustive, is presented to caution you that many areas can lead to problems. Some are obvious, while others may be expanded on as needed and time allows.
– High/Low precedence (contrary to EOD where the Backtester is unable to determine which came first, the entry/exit or the high/low, in realtime there can be no ambiguity in price precedence).
– Data Delays (real-time data may be delayed for various reasons and time periods (Internet delays, lack of quotes, packets vs. ticks, etc.).
– Low Liquidity (there may be no-volume trading periods).
– Data Holes (bars with no trades).
– Data Spikes (high spikes without volume may trigger trades).
– Data Padding (a bar without data may be padded).
– Premature Padding (the last bar may be a padded bar).
– Data Accuracy (prices you receive aren’t always accurate).
– Random Slippage (you will rarely get the expected price).
– Breakout slippage (you will rarely get the Breakout price of your system).
– Survivorship Bias (companies that didn’t do well and stopped trading won’t be in your database, i.e., you are working above average stocks).
– Lucky Trades (a series of lucky trades may look like good performance).
– Parameter Over-Optimizing (optimized parameters are rarely stable over time).
– Design Over-Optimizing (frequent testing is like running an optimization and may be leading to false conclusions).
– Out–of-Bound Prices (with PriceBoundChecking turned ON, AmiBroker forces the trade price within the High-Low range, this may hide pricing errors).
– Price Rounding (prices may be rounded or truncated by the broker).
– Wrong Use of >= and <= (when using both <= and >= in the same statement, only the first equal condition will ever be seen).
– Comparing Floating Point Numbers (calculated values can have many decimal places, either round values or use the AlmostEqual()).
– Chart Justification (make sure you are looking at the Last bar!).
– System Mortality (no system will work forever).
– Sharing Trading Systems (sharing systems with other traders may result in over-trading a system).
– Being Duped by a Trend (a rallying ticker may make your system look like the HG (holy grail).
– Tricking AmiBroker (AmiBroker has its limits; it is possible to write esoteric code that will produce wrong results).
– Order Visibility (placing your order for every trader to see may influence the orders they place).
– Making the Market (extreme example: if you place a MKT order during a no-trading period you will change the chart).
– Window/Pane Execution Order (when passing variables between panes or windows do not assume that they execute in a fixed order, more).
– Trading at the Open (order execution at the start/end of day is different from midday because of volatility and data delays).
– IB Data Snap Shots (snapshots are only representative of prices traded).
– Trade Delays (make sure you understand your trade delays when backtesting).
– EOD and Intraday Gaps (There is no time interval in RT gaps).
– Time Zones (make sure your computer and database timezones are properly set).
– Very Short Time-Frames (prices jump and are less contiguous).
– Setting LMT Prices (consider rounding for faster order executions).
– 24-Hour vs. RTH (Regular Trading Hour) Backtesting (extended hours can rarely be traded like RTH due to huge bid/ask spreads and low volume).
– Static Variables Naming (use unique names for your static variables).
– Incorrect Computer Time (computer time offset from market time can cause real problems).
– Look-Ahead Problems (not all look-ahead coding problems are obvious).
– Buy/Sell Precedence in a Loop (be aware that AB and custom AFL loops enforce a Buy/Sell priority).
– RT Candle Discrepancies (RT Candles may be different from later backfills, especially in the opening print).
– Bars Loaded (consider bars-loaded with respect to execution speed and loops).
– Signal lifetime (signal strength quickly decays over bars in high frequency trading).
– SameBarExits (Sell signals may act as a qualifier for Buy signals).
– Designing systems based on High and Low triggers (these may fill in the Backtester but not in real trading). more…
– Using the wrong CommissionMode and/or CommissionAmount can make any system look good, or bad…
– Using zero TradeDelays is OK if you code the delays in your system’s code, else you may be looking into the future.
Edited by Al Venosa