How-To

Backtest With Your Own CSV Data: Four Decisions Made Before Bar One

Loading your own candles is the easy part. Four settings picked before the first trade decide whether the result means anything: the resolution of the file, its timezone, the base timeframe, and the costs the file does not contain.

September 21, 202612 min readBy TradingSFX
Share:
Table of contents
  1. 011. Resolution: the decision worth 54R
  2. 022. Timezone: a session filter is only as right as the clock
  3. 033. The base timeframe is a one-way door
  4. 044. What the file does not contain
  5. 05Why your own data is the better arrangement anyway
  6. 06What to do with the result
  7. 07How This Works in TradingSFX
  8. 08Bottom Line

Bringing your own candles to a backtest sounds like a formality. Download a file, load it, start clicking.

The loading is the easy half. What decides whether the number at the end of the session means anything is four settings you pick before the first trade, and three of them are silent: no error appears, the chart looks normal, and the result is wrong in a direction you will not notice.

This post is about those four decisions. Where to actually get the files, with per-source export steps, is a separate walkthrough: where to get free historical data for backtesting.

1. Resolution: the decision worth 54R

Here is the failure mode nobody puts in a backtesting tutorial.

You are testing a setup on the 1-hour chart. Stop 20 pips, target 40 pips, so every trade is either minus 1R or plus 2R. You click forward, an entry triggers, and the next hourly candle has a high above your target and a low below your stop.

Which one printed first?

The hourly candle does not say. It gives you four numbers for the whole hour, and the path inside that hour is not in the file. So you decide. And the honest word for that is decide, because whatever you tell yourself, there is no data behind the choice.

Work it on 100 trades:

  • 82 trades are unambiguous. 30 winners at plus 2R, 52 losers at minus 1R. That is plus 8R, at a 37% win rate.
  • 18 trades touched both levels inside one candle.

Now resolve those 18 three ways, changing nothing else:

How you resolve the 18TotalWin rate
All as winners+44R48%
Split 7 winners, 11 losers+11R37%
All as losers-10R30%

Same file. Same entries. Same rules. The spread between the top row and the bottom row is 54R, because each of those 18 trades carries 3R of swing between plus 2 and minus 1. At 1% risk on a $100,000 account that is $54,000 of difference sitting inside a decision you made 18 times while tired and hopeful.

Two things follow.

Import the lowest timeframe you have. On 1-minute data most of those 18 trades resolve themselves, because the minute sequence shows which level printed first. The ambiguity does not vanish completely (a minute candle can still span both levels) but for a 20-pip stop it goes from common to rare. This is also why a backtester should build higher timeframes by aggregating your file rather than asking you to import each one: you replay the 1-hour chart while the 1-minute sequence underneath is still available to settle the order.

Until then, count the ambiguous ones as losses. Not because it is likely, but because it makes your test a floor rather than a guess. A strategy that survives the pessimistic reading is worth trading. One that only works when you give yourself the benefit of the doubt 18 times is a strategy about you, not about the market.

That 18-point win-rate swing is also the cleanest illustration of why the headline number is a poor target in the first place, which the win rate post works through in detail.

2. Timezone: a session filter is only as right as the clock

Every candle in your file is stamped in some timezone. Most files do not say which, and no file forces you to think about it.

Say your file is a MetaTrader export. Broker server time is usually UTC+2 in winter and UTC+3 in summer, a convention chosen so the daily candle closes at 5pm New York. So a row labelled 09:00 in the winter half of that file is really the 07:00 UTC candle.

Import it as UTC and nothing breaks. The chart draws. Price looks right. But every bar now sits two hours later than it actually happened. When you then test "London open only, 08:00 to 10:00", the backtester hands you the bars labelled 08:00 to 10:00, which are really the market from 06:00 to 08:00 UTC. You have spent the evening testing the Asia handover and writing down a conclusion about the London open.

The second-order version is worse, because it hides inside a file you picked the right zone for. Server time shifts by an hour at the daylight saving changeover. Choose a flat UTC+2 for a year of data and the winter months land exactly right while the summer months land an hour late. Split that sample by date (a check worth running anyway) and the two halves disagree for a reason that has nothing to do with the market.

The counterintuitive case is HistData, one of the most-used free sources. Its own file specification says the stamps are Eastern Standard Time without daylight saving adjustments, all year. So the correct pick is a fixed UTC-5, and picking the option named "New York time" is wrong for roughly half the year, because the file does not observe New York's clock changes even though it uses New York's winter offset.

The rule that covers all of it: pick the clock the file was written in, never the clock you want to read it in. Display timezone is a separate setting and you can change it any time. The source timezone is a property of the file.

Where this bites hardest is any strategy with an hour in its rules. Session opens, killzones, opening ranges, a news blackout window, "no trades after 3pm". If the clock is off, the test ran on different candles than the strategy describes, and the result is precise, confident and about something else.

3. The base timeframe is a one-way door

One file gives you one base resolution. Everything above it is arithmetic; everything below it is gone.

A 1-minute file can be aggregated into 5m, 15m, 1h, 4h, daily, or any whole multiple you want. A 1-hour file cannot be taken apart into anything finer, because the information was discarded by whoever built the file, not by your software.

So the import question is not "what timeframe do I trade?" It is "what is the finest resolution I might ever want from this data?" If you trade the 4-hour chart but your stops are tight enough that section 1 applies, you still want 1-minute candles underneath.

The practical cost is file size, and it is smaller than people expect. A year of 1-minute forex data is a few hundred thousand rows, which is a normal import. The ceiling in TradingSFX is 5,000,000 bars per dataset, about 13 years of 1-minute candles, and that limit is your device's memory while parsing rather than anything about replay. Past it, split by year and replay the parts back to back.

4. What the file does not contain

Four things are missing from every OHLC CSV, and each one flatters your results.

The spread. Many free forex files, HistData included, are bid quotes only. Your buy fills at the ask in real life, so the backtest gives you a better entry than you would have got, on every single long. Nothing in the data will tell you this.

Commission. Not in the file either, by definition.

Both are fixable by arithmetic rather than simulation. Convert your all-in cost into R and subtract it from the result. At 1.2 pips of total cost against a 20-pip stop, that is 0.06R per trade. On a strategy showing 0.15R per trade gross, you keep 0.09R, and 40% of the edge was never yours. It also sets a floor on what the marginal trade has to be worth, which is the same arithmetic that makes the overtrading test work.

The path inside the bar. Section 1. This is the big one.

Volume, sometimes. If your strategy reads volume, check the column actually carries numbers. MetaTrader 5 exports have both a real Volume column and a TickVolume column, and on most retail forex symbols the real one is zeros from top to bottom while the tick column holds the data. A volume profile built from the empty column is not wrong so much as empty, and it looks plausible.

None of this makes CSV backtesting unreliable. It makes it a test you have to read correctly, which is a different thing. Every one of these four is a known constant you can subtract, rather than an unknown you have to trust.

Why your own data is the better arrangement anyway

There is a version of this article that treats importing your own file as a limitation to apologise for. It is not.

You choose the market. Vendor-supplied feeds cover what the vendor licensed. Your broker's own export covers exactly the symbol you trade, with that broker's prices, including the pairs and indices nobody else bothers to carry.

You choose the depth. Replay tools that ship their own data meter it, and the history available to you on a given tier is a business decision rather than a technical one. TradingView's bar replay limits are the clearest worked example of how that plays out. A file you downloaded has whatever depth the file has, and it does not shrink when someone changes a pricing page.

It never leaves your machine. The parse happens in your browser and the bars go into local browser storage on that device. That also means the dataset is per-device: import it again on your laptop, and think of the file as yours to keep rather than something we hold for you.

The honest costs: you have to fetch the file yourself, quality varies between free sources, and one CSV is one symbol. For a two-symbol comparison, such as a divergence study between correlated pairs, you need both files imported before you start.

What to do with the result

A backtest produces a number. The number is worth what its sample is worth, and this is where most replay sessions quietly end.

Two checks before you believe anything:

Count the trades against the edge you are claiming. A small edge on noisy outcomes needs far more trades than the round numbers people repeat. How many backtest trades you actually need derives the requirement from your own average result and its spread, and the answer ranges from about 100 trades to several thousand depending on your reward multiple.

Delete your best trade and recompute. If the edge lives in one candle, it is not an edge.

And log the trades in a form you can cross-filter later. A replay session that produces a win rate and nothing else cannot answer the question you will have in three weeks, which is not "does this work" but "which version of this works". Recording each trade in R rather than currency is what makes a replay sample comparable to your live one, and the R-multiple post covers the traps in that column, including the one where a stop you moved leaves no trace.

If the file you are working from is a MetaTrader export, it is worth knowing what that export does and does not carry before you build a routine on it. MetaTrader trade history export covers the four things no MT export contains.

How This Works in TradingSFX

The replay backtester takes any plain CSV with time, open, high, low and close columns. Header or no header, comma, semicolon or tab separated, split date and time columns or a combined stamp, MetaTrader's own format, epoch seconds, ISO stamps, or the punctuation-free format the free data sites use. Trailing columns it does not recognise are ignored rather than treated as an error.

On import you set three things: the symbol name, the timeframe the file holds, and the timezone it was stamped in. That last picker carries the daylight-saving-aware options as well as fixed offsets, so MetaTrader server time, New York and London are one choice for the whole year rather than a decision that is right for half of it. If you pick wrong, the dataset list lets you change the timezone afterwards and re-times the bars in place.

Higher timeframes are built from your import, so one 1-minute file gives you the whole ladder above it. Large files parse in batches with a progress bar, and replay stays responsive on multi-million-bar datasets because the chart works through a moving window rather than holding everything at once.

Replay, drawings, indicators, news markers and live practice trades with draggable stops and targets are open on every plan, including the free one. What sits on Pro is saving a practice trade into your journal with its notes, strategy and confluences attached, plus custom timeframes such as a 3-minute built from 1-minute data. On the free plan the close form still runs in full and your last 10 practice trades are held for 30 days, so they can be imported into the journal if you upgrade rather than being lost.

What the backtester deliberately does not do is simulate what your file does not contain. There is no spread or commission modelling and no intrabar fill reconstruction. Costs are yours to subtract, for the reason in section 4: a simulated cost is a number we invented, and it would make the result look more precise than it is.

Basic is free forever at 10 trades a month with no card. Pro is $19.99/mo and Premium is $29.99/mo, both with a 7-day trial.

Bottom Line

The file is not the hard part. The four decisions around it are.

Import your lowest timeframe, because resolution is the only one you cannot fix later. Set the source timezone to the clock the file was written in, or every hour-based rule you test is about a different part of the day. Subtract your costs in R instead of hoping they are small. And when a single candle holds both your stop and your target, count it as a loss and let the strategy earn its result.

Get those four right and a replay session produces something rare: a number you can act on without arguing with it later.

Try it on the sample demo with no account, or read what the backtester does before importing your own file.


Published September 21, 2026. External facts checked on 21 September 2026: HistData's ASCII file specification (Eastern Standard Time without daylight saving adjustments, bid quotes, YYYYMMDD HHMMSS stamps) from histdata.com's own data-files specification page, and TradingView's Export chart data option being listed as a paid-plan feature on TradingView's own support documentation. Both domains are blocked by our research proxy, so each figure comes from indexed extracts of those vendors' own pages corroborated across two independent searches. MetaTrader broker server time (UTC+2 winter, UTC+3 summer, aligned to the 5pm New York close) is a platform convention rather than a vendor claim and was confirmed across independent sources on the same date. The MetaTrader 5 dual volume column behaviour is our own finding from handling those files. No competitor pricing is quoted. All arithmetic is worked openly from a stated illustrative 100-trade sample, and no survey or study figures are used. TradingSFX plan details and import limits were verified against the application code on 21 September 2026.

Free to start

Turn your trades into a real edge

Stop guessing what works. Log your trades, track confluences, and let the AI Coach surface the patterns you keep missing across every prop firm rule and strategy.

No credit card required · Start for free

Not financial advice. This article is for educational and informational purposes only and does not constitute financial, investment, or trading advice. Trading forex, indices, crypto, and other leveraged instruments carries a high level of risk and can result in the loss of all your capital. Past performance is not indicative of future results. Always do your own research and consider consulting a licensed financial advisor before making any trading decision.
All third-party names and trademarks mentioned in this article are the property of their respective owners. References are made for descriptive and comparative purposes only. TradingSFX is not affiliated with, endorsed by, or sponsored by any third party mentioned. See our Terms of Service for the full trademark disclaimer.

    We use cookies for analytics to improve your experience. Privacy Policy