MeowQuant is an independent third-party information site, not OKX official. The sign-up button carries invite code OK30001, and we may earn a promotion fee from it. Full disclosure →

OKX · Quant Hands-On

How to Backtest a Strategy: Pulling Historical OHLCV With ccxt

Once people have learned how to place an order through the API, they usually do one of two things next: point the script straight at real money, or dive into the demo account and spend days watching it tick along. Both routes skip the step in the middle that saves the most time, which is the backtest. The idea behind a backtest is simple: take market data that has already happened, run your strategy logic through it on fast-forward, and cover several years of price action in a few minutes instead of burning a day of real time for every day of results.

This piece fills that gap. We (the MeowQuant desk) walk through where a backtest and a demo run actually differ and what order to do them in, pull a stretch of OKX historical candles with ccxt, pair it with pandas for a minimal but working dual-moving-average example, then go through the traps that catch beginners and which lines of a backtest report deserve your attention instead of the single number at the end. To say it plainly up front: the dual-MA example below exists to teach the workflow. The parameters are illustrative, it is not a tuned money-making strategy, and passing a backtest does not mean it will earn anything live.

invite_codes.env1

Backtesting and paper trading are not the same thing

Start by keeping the two apart. A backtest runs on historical data: you drop your strategy logic in and let it play from one end of the record to the other. The upside is speed, since years of price action finish in seconds to minutes. The downside is that it is hindsight by nature, running inside a world whose ending is already known. Paper trading (demo trading) runs on live data, and the strategy walks forward day by day at the market's own pace. The upside is that it sits much closer to real execution, because the order placement, the fills, and the network latency are all genuine. The downside is that it is slow, and validating one idea can take weeks.

They are not an either-or choice, they are a relay. Use the backtest first to throw out ideas that clearly go nowhere, because a strategy that cannot even beat sitting on your hands across historical data rarely deserves the next step. Once it clears that bar, take it to the demo account and let it walk at real-world pace, checking that the execution layer holds up too: whether orders hang, whether the logic goes haywire when the connection drops. Only when both stages are behind you does a small amount of real money you would not mind losing come into the picture. If you are still fuzzy on what quant trading even is, the plain-English intro is a better place to start.

A minimal backtest: historical candles plus a dual-MA example

Backtesting does not need elaborate tooling. Two pieces are enough to get moving: ccxt to pull historical data from the exchange, and pandas to shape that data into a table and do the arithmetic. The snippet below shows how to pull a stretch of BTC/USDT daily candles from OKX. Historical market data goes through the public data endpoint, so no API Key is needed:

import ccxt
import pandas as pd

# Pulling historical market data uses a public endpoint, no API Key needed
okx = ccxt.okx()

# Pull BTC/USDT daily candles, the most recent 500 (sample size is illustrative, adjust it yourself)
ohlcv = okx.fetch_ohlcv('BTC/USDT', timeframe='1d', limit=500)

df = pd.DataFrame(ohlcv, columns=['ts', 'open', 'high', 'low', 'close', 'volume'])
df['ts'] = pd.to_datetime(df['ts'], unit='ms')
df.set_index('ts', inplace=True)

print(df.tail())

With the data in hand, use pandas to compute two moving averages and write the most basic dual-MA signal there is: when the short average crosses above the long one, treat it as buy and hold; when it crosses below, treat it as flat. This is the simplest idea in the textbook, used here to demonstrate the full backtest workflow. The parameters (10 and 30) are illustrative and have not been tuned with any seriousness, so do not lift them straight into live trading:

# Dual-MA demo strategy: short above long = hold, short below long = flat
# The parameters are illustrative, not "tuned to make money" values, do not copy them into live trading
SHORT, LONG = 10, 30

df['ma_short'] = df['close'].rolling(SHORT).mean()
df['ma_long']  = df['close'].rolling(LONG).mean()

# Judge on the "previous" candle's MA relationship, to avoid look-ahead bias
df['signal'] = 0
df.loc[df['ma_short'].shift(1) > df['ma_long'].shift(1), 'signal'] = 1   # hold
df.loc[df['ma_short'].shift(1) <= df['ma_long'].shift(1), 'signal'] = 0  # flat

# Multiply the "current" candle's return by the signal set on the previous one, a rough estimate (no fees/slippage, illustrative only)
df['ret']      = df['close'].pct_change()
df['strategy'] = df['ret'] * df['signal'].shift(1)

print('Illustrative cumulative return (no fees deducted, workflow demo only):', (1 + df['strategy'].fillna(0)).cumprod().iloc[-1])

Run that and you get a crude "illustrative return" figure. Note that nothing has been deducted for fees or slippage here, and funding rates and order queuing are not accounted for either, so the number exists to help you follow the arithmetic of a backtest, not to answer how much this strategy "can earn." If you have never created an API Key or used ccxt before, go back over the connection and order basics in our API quant intro first. The backtest stage needs no Key, but you will want one once you hook up to a live account.

Risk note: The two snippets above exist to teach the workflow. They are not investment advice, a backtest result is no guarantee of future profit, and the parameters should not be copied straight into live trading. Pulling historical market data uses the public endpoint and needs no API Key. When you later connect your own account for real-time validation or live trading, tick only the "read" permission when creating the Key, and leave trade and withdrawal permissions until the step where you are genuinely ready to place orders.

The four traps beginners fall into

A backtest that produces a beautiful equity curve does not mean the strategy is sound. Almost every beginner walks into the four traps below at least once, and knowing about them ahead of time saves a lot of detours.

Overfitting: tuning until history fits perfectly is exactly what makes it dangerous

Overfitting means adjusting parameters over and over until the backtest result sits flush against that one stretch of historical data. The high-return curve you get at that point has most likely just memorized the coincidences inside that particular window rather than uncovered a real pattern. Move those parameters onto market conditions they have never seen and they are usually the first to fail, which is why the more "perfect" a backtest looks, the more it is worth asking whether you overdid it. The defense is to keep your parameter grid coarse rather than fine, and once the backtest is done, validate it separately on a stretch of data that took no part in the tuning: an out-of-sample test, walking the strategy forward onto candles it has never seen. Only if both stretches hold up does the result count for anything.

Fees and slippage left out of the math

Plenty of beginner backtests count only the price difference, deducting no fees and simulating no slippage, slippage being the gap between the price you place an order at and the price it actually fills at. Both matter enormously for strategies that trade often. Even if a single trade costs only a few basis points, a hundred trades stack up and eat a serious chunk of the return. When you write a backtest, at minimum deduct the cost of every trade at OKX's actual fee rates, then add a conservative slippage estimate on top. Only then is the number you compute worth trusting.

Testing only a bull-market stretch

Pick a one-way rally out of history to backtest on and almost any buy-and-hold strategy looks good. Markets do not stay one-way forever, though, so your data window needs to cover at least the different phases: up, down, and sideways. How a strategy behaves in chop and in a downtrend usually says more than whatever number it posts through a bull run.

Look-ahead bias: using data you should not have known yet

Look-ahead bias is the most hidden and most easily committed error of the four. The usual version is using a candle's closing price to decide whether to buy or sell at that same candle's open. In reality the close is only known once the candle has finished, but the backtest code "sees" it early, and the return it reports ends up clearly overstated. The shift(1) in the sample code above pushes the signal back by one slot so that the judgement uses only "the previous, already-finished candle," and that is precisely what sidesteps the problem. A decision may draw only on history that has already settled, never on the candle still in progress.

Reading a backtest report: look past the finish line

When a backtest finishes, most people's first instinct is to look at the total return at the end, which is the least useful way to read it. Two strategies can both post "up 30 percent" while one climbs steadily the whole way and the other loses half its value before clawing back. Whether you could actually have held either one is a completely different question. At a minimum, a backtest report deserves these three passes:

  • The shape of the equity curve. Do not just look at the endpoint, look at the whole path: smoothly rising, or wild swings with a couple of rollercoaster rides before it scrapes back to even. The shape says far more than the final figure about what holding this strategy would actually feel like.
  • Maximum drawdown. How far it fell from the curve's peak to the trough that followed. This is the line in the report that deserves the most respect, because it roughly answers "how much unrealized loss you would have to sit through at the worst moment." If the drawdown is too deep, you probably could not have held on no matter how good the ending looks. It ties directly into writing position limits and stops into your code, so the two are worth reading together.
  • Win rate paired with the payoff ratio. A high win rate does not mean profit. You also need to know how much an average winner makes and how much an average loser costs, which is the payoff ratio. A 70 percent win rate that wins small and loses big still bleeds money over time, while a 40 percent win rate that wins big and loses small can be a perfectly good ledger. Read the two numbers together, because either one on its own will mislead you.

Passing a backtest is not a profit, so what is next

However pretty a backtest looks, it was produced inside an idealized environment: no real order queuing, no network latency, and no way to model whether you personally will freeze up or change your mind halfway through. Clearing a backtest only says the idea is worth carrying one step further. It is not the finish line.

The next step is the demo account, where the same logic runs at real-world pace and you find out whether the execution side still has problems. Once the demo run is smooth too, put in an amount of real money you would not mind losing rather than jumping straight to a large position. Before you actually step onto the field, get the risk controls in place as well, including position caps and stops written into the code. Backtesting and paper trading validate the strategy logic, while risk control is what keeps a wrong call from doing lasting damage.

One line is worth repeating to yourself over and over: the past is not the future. Every piece of data a backtest touches has already happened. It can tell you what would have occurred if you had done this in the past, and it cannot tell you the future will behave the same way. Treat a backtest as a filter rather than a crystal ball and the road ahead gets a good deal steadier.

FAQ

What is the difference between a backtest and paper trading, and which one comes first?

A backtest fast-forwards your strategy logic through historical market data, so a few minutes of compute can cover several years of price action and quickly weed out ideas that clearly do not work. Paper trading follows the live order book at real speed with virtual money, so it reflects real queuing and latency far better. The normal order is backtest first to filter ideas, then paper trading to run the surviving idea at real-world pace, and only after that a small amount of real money.

What is overfitting, and why is it called the biggest trap in backtesting?

Overfitting is what happens when you tune parameters over and over until the result hugs one stretch of history perfectly. The beautiful equity curve you get at that point has most likely just memorized the coincidences in that period rather than found a real pattern. The moment those parameters meet market conditions they have never seen, they tend to be the first to fail, which makes overfitting the most dangerous trap in backtesting and the one beginners are most likely to read as good news.

What does look-ahead bias mean in a backtest?

Look-ahead bias means the strategy quietly uses data it could not possibly have had at the moment it made the decision. The classic coding mistake is using a candle's closing price to decide whether to buy or sell at that same candle's open. In reality the close is only known once the candle has finished, but the backtest code reaches for it early, so the returns come out clearly overstated. The way to avoid it is to let every decision use only candles that have already closed.

My backtest equity curve looks great. Can I go live with real money now?

Not recommended. A backtest is an idealized environment with no real slippage, no order queuing, no network latency, and no way to price in your own hesitation and fat fingers. Passing a backtest only means the idea is worth taking one step further. Next comes paper trading, running the same logic at real-world pace to confirm the execution side holds up, and only then risking an amount of real money you would not mind losing. Results measured on historical data do not guarantee the future will repeat them.

How much do fees and slippage change a backtest result?

A lot, especially for strategies that trade often. Plenty of beginner backtests count only the price difference between buying and selling, with no fees deducted and no slippage simulated, slippage being the gap between the price you send an order at and the price you actually fill at. Numbers built that way usually come out well above what you could really collect. Even simply deducting the cost of every trade at OKX's actual fee rates can grind away the profit of some high-frequency strategies that looked fine at first glance.

Add backtesting and the quant workflow is complete: understand the concepts, backtest to filter ideas, use the demo account to validate execution, then step in with a small stake and your risk controls attached. Skip none of it and you will spare yourself a lot of problems that were findable in advance. If you would rather pick a strategy type that needs no code at all, open the quant strategy comparison table and see how grid, DCA, copy trading, and hand-written scripts stack up.