Data Format Reference

Kibot delivers historical market data as plain text files with a small, stable family of schemas. Tick, second, minute, daily, aggregate bid/ask, NinjaTrader, and TradeStation formats all share a common core, comma-delimited, timestamps defaulting to Eastern Time (the time zone can be changed to suit your needs), no header row, with well-defined variations for each use case. This page is the canonical field-by-field specification so that a reader can unambiguously parse any Kibot file.

Overview

All Kibot data files share these characteristics:

  • Delimiter: Comma (,) for all standard formats; semicolon (;) for NinjaTrader formats
  • Timestamps: Eastern Time (ET) by default, EST (UTC-5) or EDT (UTC-4) depending on the date; the time zone can be changed to suit your needs
  • Date format: MM/DD/YYYY for standard formats; yyyyMMdd for NinjaTrader formats
  • Header row: None. Data begins on the first line.
  • File type: Plain text (.txt)
  • Encoding: ASCII / UTF-8

Timestamp convention matters. For bar data (second, minute, daily), the timestamp represents the bar open time, the moment the bar begins, not when it closes. A bar stamped 10:30:00 on 1-minute data covers the period from 10:30:00 through 10:30:59. This convention is consistent across all Kibot standard formats and differs from the NinjaTrader and TradeStation conventions described below.

Tick Formats

Tick data captures every individual trade or quote update. The standard format records the trade time to the second; an experimental millisecond-timestamp variant also exists for US stocks and ETFs. Each comes with or without bid/ask quotes.

Tick with Bid/Ask

Six fields per row.

Date,Time,Price,Bid,Ask,Size

Example:

09/15/2025,10:30:15,4520.50,4520.25,4520.75,3

Tick without Bid/Ask

Four fields per row.

Date,Time,Price,Size

Example:

09/15/2025,10:30:15,4520.50,3

Millisecond Tick with Bid/Ask (experimental)

Nine fields per row. Same trade records as the standard format, with milliseconds added to the Time field as HH:MM:SS.mmm. This variant is experimental and not officially supported.

Date,Time.mmm,Price,Bid,Ask,Size,BasisForLast,TotalVolume,TradeConditions

For full documentation of the millisecond tick fields, see Tick data.

Millisecond Tick without Bid/Ask (experimental)

Four fields per row. The Time field includes milliseconds.

Date,Time.mmm,Price,Size

Example:

09/15/2025,10:30:15.247,4520.50,3

Second-Level Formats

Available intervals: 1s, 5s, 10s, 15s, 30s, 60s. All second-level formats use the same field structure:

Date,Time,Open,High,Low,Close,Volume

Example (5-second bar):

09/15/2025,10:30:00,4520.25,4520.75,4520.00,4520.50,150

The Time field is in HH:MM:SS format. The timestamp represents the bar open time.

Minute Formats

Available intervals: 1, 2, 3, 5, 10, 15, 30, 60 minutes. All minute formats use the same field structure:

Date,Time,Open,High,Low,Close,Volume

Example (5-minute bar):

09/15/2025,10:30:00,4520.25,4525.00,4518.50,4523.75,4200

The Time field is in HH:MM:SS format. The timestamp represents the bar open time.

Daily Format

Daily files have no Time field, one row per trading day.

Date,Open,High,Low,Close,Volume

Example:

09/15/2025,4515.00,4525.75,4510.25,4520.50,1250000

Aggregate Bid/Ask Format

Ten fields per row. Used primarily for forex pairs and some other instruments where bid/ask data is more relevant than last-trade data.

Date,Time,BidOpen,BidHigh,BidLow,BidClose,AskOpen,AskHigh,AskLow,AskClose

Example (1-minute bar):

09/15/2025,10:30:00,1.08520,1.08535,1.08510,1.08530,1.08540,1.08555,1.08530,1.08550

This format does not include a volume field. For forex, volume is typically measured by tick count rather than actual traded volume (see the Instrument Type Differences table below).

NinjaTrader 8 Formats

NinjaTrader 8 uses semicolons (;) as delimiters and a yyyyMMdd date format. No header row. Files should use a .txt extension.

NinjaTrader timestamps represent the end of bar time by convention, a 1-minute bar stamped 09:31:00 covers the period 09:30:00 through 09:30:59. This differs from Kibot's standard format, which uses bar open time. Kibot's NinjaTrader-format exports follow the NinjaTrader convention.

NinjaTrader Minute

yyyyMMdd HHmmss;Open;High;Low;Close;Volume

Example:

20250915 103100;4520.25;4525.00;4518.50;4523.75;4200

NinjaTrader Daily

yyyyMMdd;Open;High;Low;Close;Volume

Example:

20250915;4515.00;4525.75;4510.25;4520.50;1250000

NinjaTrader Tick

yyyyMMdd HHmmss;Price;Volume

Example:

20250915 103015;4520.50;3

For file naming conventions in NinjaTrader, the recommended format is {Instrument}.{DataType}.txt (e.g., ES 12-25.Last.txt). Import through NinjaTrader's Historical Data Manager under Tools > Historical Data Manager > Import.

TradeStation Format

TradeStation accepts comma-delimited, tab-delimited, or space-delimited ASCII files. The date format is flexible (MDY, YMD, or DMY, specified during import). An optional header row can define field order. Files typically use a .txt or .asc extension.

TradeStation Minute/Daily

"Date","Time","Open","High","Low","Close","Volume"

Example (with header, comma-delimited):

"Date","Time","Open","High","Low","Close","Volume"
09/15/2025,10:30:00,4520.25,4525.00,4518.50,4523.75,4200

TradeStation Tick

"Date","Time","Close","Volume"

TradeStation uses "Close" as the field name for the tick price. Open, High, and Low fields are optional but must be included or omitted together. TradeStation timestamps represent bar close time. Consult TradeStation's documentation for specific import settings under Format > Symbol > Lookup.

Conversion Rules

Kibot data supports upward aggregation only, you can build larger timeframes from smaller ones, but not the reverse. Daily bars cannot be broken back into minute bars; the intrabar price path is lost once aggregation has happened.

How OHLCV Aggregates

Field Aggregation Rule
Open First Open in the period
High Maximum High across all bars
Low Minimum Low across all bars
Close Last Close in the period
Volume Sum of all Volume values

Format Compatibility Matrix

This table shows which source formats can be converted to which target formats.

Source Format Possible Targets
Tick Seconds (1-60s), Minutes (1-60min), Daily, Weekly, Monthly, Yearly, NinjaTrader, TradeStation
1-Second Larger seconds (5-60s), Minutes (1-60min), Daily, Weekly, Monthly, Yearly
1-Minute Larger minutes (2, 3, 5, 10, 15, 30, 60), Daily, Weekly, Monthly, Yearly
5-Minute 10, 15, 30, 60-min, Daily, Weekly, Monthly, Yearly
15-Minute 30, 60-min, Daily, Weekly, Monthly, Yearly
30-Minute 60-min, Daily, Weekly, Monthly, Yearly
60-Minute Daily, Weekly, Monthly, Yearly
Daily Weekly, Monthly, Quarterly, Yearly
Weekly Monthly, Quarterly, Yearly
Monthly Quarterly, Yearly

Conversion to NinjaTrader or TradeStation format is available from any source resolution, it is a format change, not an aggregation. For a planned tool that automates these conversions, see Data format converter.

Market sessions and timestamp semantics

Stock and ETF intraday files cover three distinct US sessions: pre-market from 8:00 AM to 9:30 AM ET, regular trading from 9:30 AM to 4:00 PM ET, and after-market from 4:00 PM to 6:30 PM ET. All three sessions are included in the same file, there is no separate pre-market or after-market product to buy. For highly liquid instruments such as SPY and a handful of other active ETFs and stocks, the effective coverage extends further, typically starting at 4:00 AM and ending at 8:00 PM ET (per the Kibot format documentation).

A bar's timestamp marks the moment the bar opens, so a row stamped 10:00:00 on a 1-minute file represents the period from 10:00:00 through 10:00:59. This is consistent across tick, second, minute, and daily standard files; the NinjaTrader-format exports described elsewhere in this article follow the opposite (bar-close) convention because NinjaTrader itself does.

Periods with no activity

If no trades occur during a given interval, Kibot simply omits the bar rather than emitting a zero-volume placeholder. The next row in the file is the next bar with actual activity, and any gap between its timestamp and the previous row's timestamp corresponds to time during which nothing was reported. This pattern is most visible in pre-market and after-hours data for illiquid stocks, where long stretches can pass without a print. Code that iterates Kibot files by wall-clock time, rather than by row, must reconstruct the empty intervals itself.

Daily close price

In daily files the closing price is the last trade recorded before 16:00 ET, which normally matches the Close field of the 15:59 bar in the corresponding intraday file. For less liquid stocks the last intraday bar of the regular session may fall earlier, and the daily Close follows that bar rather than inventing a 16:00 value. Analysts who reconcile daily and intraday data benefit from this consistency: the daily Close and the last regular-session intraday Close are the same number.

Exponential price formatting

Very small values are written in scientific notation. A price recorded as 1E-06 stands for 0.000001. Kibot's rule of thumb is that any value below one with five or more decimal places may be exported in exponent form, so parsers that assume fixed-point decimals will mis-read these rows. The values themselves are exact; it is only the textual representation that switches.

Split and dividend adjustment on intraday files

All standard intraday and daily files are adjusted for stock splits and dividends by default. The adjustment method tracks Yahoo Finance's historical series, since a large fraction of Kibot customers cross-check against Yahoo, so values on both sides should agree after both have applied the same back-adjustment rules (per Kibot's data-format documentation).

Volume is adjusted alongside price so that the product price × volume is preserved through any split. Before a 2:1 split a share might trade at ten dollars with a hundred-share volume; after the split the same moment is recorded at five dollars with two hundred shares, and the dollar turnover stays at one thousand. Keeping this invariant means aggregations like VWAP and dollar-volume remain comparable across split events without further correction. For the full reasoning and for the unadjusted variants of the same files, see Adjusted vs unadjusted data.

Instrument Type Differences

Type Price Data Volume Notes
Stocks / ETFs Last + Size Real exchange volume Includes pre-market and after-hours sessions
Forex Bid / Ask Tick count only No real volume, forex is an OTC market with no centralized exchange
Futures Last + Size Real exchange volume Settlement price may differ from last trade (close) on daily bars
Indexes Calculated value None or calculated No tradeable volume, indexes are computed from component prices

The divergence between settlement price and last-trade close on futures daily bars is a common source of apparent mismatch against third-party data providers (per kibot's support Faq).

Key Takeaways

  • All Kibot standard files are headerless, comma-delimited text files with timestamps defaulting to Eastern Time (the time zone can be changed to suit your needs); NinjaTrader variants use semicolons and yyyyMMdd dates instead.
  • Kibot bar timestamps are bar open time; NinjaTrader timestamps are bar close time; TradeStation also uses bar close, be explicit about which convention a file follows before parsing.
  • Tick files come in four variants (with/without bid/ask, millisecond or second precision); minute and second bar files share a common Date,Time,O,H,L,C,V schema across all intervals.
  • Aggregation is one-way: smaller timeframes can be rolled up into larger ones using standard OHLCV rules, but daily data cannot be disaggregated back into minute data.
  • Forex uses an Aggregate Bid/Ask schema with no volume field; volume for forex, when present in tick data, is tick count rather than true exchange volume.