SPB Git forge

spb/hfmarketdata

Public

Open high-frequency market data platform — FirstRate full-history downloader, DuckDB/Parquet lake, open REST API and React docs platform (www.hfmarketdata.io)

127commits 1branches 0releases
24.7 MBsize
maindefault branch
11 days agolast push
JavaScript 53.7% Python 38.3% CSS 4.6% TypeScript 3.1%

docs: guide Charting réécrit (aucune limite pour le site, bibliothèque et réglages d'indicateurs, 45 outils de dessin en groupes, replay, layouts, templates, raccourcis, URL multi-charts, mobile) + section Charts du README web (architecture ChartsPage/ChartView, gardes moteur v2)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Simon-Pierre Boucher committed 18 days ago (Sep 7, 2026) parent c1b0795

2 changed files +100 −37

modified hfmarketdata/web/README.md +22 −9
@@ -175,21 +175,34 @@ Every reference page's **Try it** button and the MDX `<TryIt>` component produce
175 175
176 176 ## Charts (`/charts`)
177 177
178 −TradingView-class charting built **from scratch** — no lightweight-charts, no third-party engine.
178 +TradingView-class charting built **from scratch** — no lightweight-charts, no third-party engine. Free, no account,
179 +**no data limit**: every request of the page carries `X-HFMD-Client: charts`; together with the browser's
180 +`Sec-Fetch-Site` and same-host `Origin`/`Referer` the API recognises the site's own calls (principal `site`,
181 +`docs/accounts-ratelimit.md`) and serves them outside of the quota system. The page has no quota UI at all.
179 182
180 183 - `src/charts/engine/` — canvas 2D engine, zero dependencies (see `src/charts/CONTRACT.md` for the public API and
181 184 `src/charts/README.md` for the architecture: index-based time scale, layered canvases, panes, 9 series types,
182 185 drawings with undo/redo, decimation for 200k+ bars). Unit tests: `npm run test:charts` (`node --test`).
183 186 Visual harness: `dev/charts-harness.html` (`npm run charts:shots` takes the reference screenshots).
184 −- `src/charts/indicators/` — pure indicator math (SMA/EMA/WMA/VWAP, Bollinger/Keltner/Donchian, Supertrend,
185 − Ichimoku, RSI/MACD/Stoch/ATR/OBV/ADX/CCI/MFI, volume MA, Heikin-Ashi). `null` until the window is full.
187 +- `src/charts/indicators/` — pure indicator math. `null` until the window is full.
186 188 - `src/charts/data/` — API layer: symbol resolution (all assets, futures roots and contracts), bar loading with
187 − backward pagination (`order=desc` + `end`), merged range cache, quota-aware limits, URL/localStorage state.
188 −- `src/pages/charts/` — the page: toolbar, symbol combobox, indicators/compare/adjustment menus, drawing bar,
189 − HTML legend fed by `crosshairMove` (aria-live), bars table + CSV, bottom sheet on mobile. Deep link:
190 − `/charts?s=AAPL&asset=stock&tf=1day&type=candles&ind=sma:20,ema:50,rsi:14&cmp=MSFT&scale=log&vol=1`.
191 −- A signed-in browser gets the account tier on data calls (session cookie → `user:<id>` principal), so no key
192 − needs to be pasted; keyless visitors see the 429 countdown with a sign-in CTA.
189 + generous first windows (10 000 daily / hourly / 30-min, 15 000 5-min, 20 000 1-min bars) and chained backward
190 + pagination (`order=desc` + `end`, prefetch under 1 000 bars left, comparisons paginated too), merged range cache,
191 + URL / localStorage state (multi-chart `layout=`, `s2=`…), chart templates (`templates.js`).
192 +- `src/pages/charts/` — the page. `ChartsPage.jsx` owns the layout (1 / 2h / 2v / 4 `ChartView`s), the toolbar bound
193 + to the active chart, the dialogs, the keyboard and the URL; `ChartView.jsx` owns one engine instance (data,
194 + indicators, comparisons, drawings, replay, sync). Around them: `IndicatorLibrary` (⌘I: search, categories,
195 + favourites, active list), `IndicatorSettings` (Inputs / Style / Visibility, live), `DrawingBar` with flyouts
196 + (`drawtools.js` groups; tools the loaded engine does not list are hidden) + `DrawingProps` floating bar,
197 + `ReplayBar`, `ContextMenu`, `ShortcutsDialog`, `Legend` (values per plot, hide / ⚙ / ✕, `aria-live` description of
198 + the visible range), bottom sheets on mobile. Deep link:
199 + `/charts?s=AAPL&tf=1day&type=candles&ind=sma:20,ema:50,rsi:14&cmp=MSFT&scale=log&layout=2h&s2=MSFT&tf2=1hour`.
200 +- **Engine v2 (additive) is used behind `typeof chart.x === 'function'` guards** so the page also runs on the v1
201 + engine: `listIndicators()` (catalog merge in `indicators.js`), `updateIndicator(id, { params, plots, levels })`,
202 + `drawingSelect` / `selectionChange` + `textEdit` events, `getDrawingStyle` / `setDrawingStyle` / `setDrawingText` /
203 + `drawingSelect(id)`, `setReplay({ index })` (v1: emulated by slicing the data), `addPriceLine` (v1: dashed hline),
204 + `toPNG({ legend })`, `toCSV`, `describeVisible`, `setGrid`, `setCrosshairPosition` (crosshair sync). E2E tests that
205 + need v2 are `test.fixme` in `e2e/charts.spec.js`.
193 206
194 207 ## Prerender (LCP)
195 208
modified hfmarketdata/web/content/guides/charts.mdx +78 −28
@@ -1,70 +1,123 @@
1 −export const meta = { title: 'Charting', description: 'The /charts page: every symbol of the API from 1-minute to daily, series types, indicators, comparisons, drawing tools, keyboard shortcuts, shareable URLs and the data limits behind them.' }
1 +export const meta = { title: 'Charting', description: 'The /charts page: every symbol of the API from 1-minute to daily, 1 / 2 / 4 chart layouts, indicator library and settings, 45 drawing tools, bar replay, templates, keyboard shortcuts, shareable URLs — free, no account, no limit.' }
2 2
3 3 export const snippets = [
4 4 {
5 5 title: 'The same bars the chart loads',
6 − curl: `# newest 1 500 daily bars, exactly what /charts requests on first load
7 −curl "https://www.hfmarketdata.io/v1/bars/stock/AAPL?timeframe=1day&order=desc&limit=1500"
6 + curl: `# newest 10 000 daily bars — the whole history of most symbols in one call, exactly what /charts requests first
7 +curl "https://www.hfmarketdata.io/v1/bars/stock/AAPL?timeframe=1day&order=desc&limit=10000"
8 8
9 −# scrolling left loads the next page: end = oldest bar already on screen − 1 day
10 −curl "https://www.hfmarketdata.io/v1/bars/stock/AAPL?timeframe=1day&order=desc&limit=1500&end=2018-09-30"`,
9 +# scrolling left loads the next page: end = oldest bar already on screen − 1 bar
10 +curl "https://www.hfmarketdata.io/v1/bars/stock/AAPL?timeframe=1min&order=desc&limit=20000&end=2024-03-01%2009:30:00"`,
11 11 python: `import pandas as pd
12 12
13 −url = "https://www.hfmarketdata.io/v1/bars/stock/AAPL?timeframe=1day&order=desc&limit=1500&format=csv"
13 +url = "https://www.hfmarketdata.io/v1/bars/stock/AAPL?timeframe=1day&order=desc&limit=10000&format=csv"
14 14 bars = pd.read_csv(url, parse_dates=["datetime"]).sort_values("datetime")
15 15 print(bars.tail())`,
16 − javascript: `const res = await fetch("https://www.hfmarketdata.io/v1/bars/stock/AAPL?timeframe=1day&order=desc&limit=1500");
16 + javascript: `const res = await fetch("https://www.hfmarketdata.io/v1/bars/stock/AAPL?timeframe=1day&order=desc&limit=10000");
17 17 const { data } = await res.json();
18 18 console.log(data.length, "bars, newest first:", data[0]);`,
19 19 r: `library(readr)
20 −bars <- read_csv("https://www.hfmarketdata.io/v1/bars/stock/AAPL?timeframe=1day&order=desc&limit=1500&format=csv")
20 +bars <- read_csv("https://www.hfmarketdata.io/v1/bars/stock/AAPL?timeframe=1day&order=desc&limit=10000&format=csv")
21 21 tail(bars[order(bars$datetime), ])`,
22 22 },
23 23 ]
24 24
25 25 # Charting
26 26
27 −[/charts](/charts) is a full-screen chart on top of the API — every stock, ETF, index, FX pair, crypto asset, continuous futures series and individual futures contract, from 1-minute to daily bars. Nothing is pre-computed on a server: the page calls the same public endpoints you would, draws them with a purpose-built canvas engine, and only ever spends your quota when you ask for more data.
27 +[/charts](/charts) is a full-screen chart on top of the API — every stock, ETF, index, FX pair, crypto asset, continuous futures series and individual futures contract, from 1-minute to daily bars. Nothing is pre-computed on a server: the page calls the same public endpoints you would and draws them with a purpose-built canvas engine.
28 28
29 −## Symbols and timeframes
29 +<Callout type="tip" title="No account, no limit">
30 +The charts are free to use without signing in and **without any data limit**: the API recognises the page's own requests (a same-origin `X-HFMD-Client: charts` header) and serves them outside of the rate-limit system — no request counter, no rows quota, no 429 for quota reasons. The only guard is a DoS protection (1 200 requests per minute per address) that a human cannot reach. The [rate limits](/docs/rate-limits) apply to your own programs calling the API, not to the charts page.
31 +</Callout>
32 +
33 +## Symbols, timeframes, history
30 34
31 35 Press <kbd>/</kbd> (or <kbd>⌘</kbd> <kbd>/</kbd>) to focus the symbol box and start typing. Results are grouped by asset — stocks, ETFs, indices, continuous futures (`ES`, `CL`…), individual contracts (`ESZ24`), crypto, FX — with prefix matches first, then substring matches, and your recent symbols when the box is empty. <kbd>↑</kbd> <kbd>↓</kbd> move, <kbd>Enter</kbd> picks, <kbd>Esc</kbd> closes.
32 36
33 37 The timeframe switch offers the five intervals of the dataset: **1m · 5m · 30m · 1h · 1D**. Switching keeps the previous chart on screen at reduced opacity until the new bars arrive — there is never a blank flash. Intraday stamps are the exchange's US/Eastern wall-clock time for the v1 assets (badge **ET**) and UTC for individual futures contracts (badge **UTC**), exactly as documented in [Time zones &amp; sessions](/docs/time-zones).
34 38
39 +The first load is generous — the whole daily history in one call (10 000 bars), 10 000 hourly / 30-minute bars, 15 000 five-minute bars, 20 000 one-minute bars — and older history streams in as you scroll left: the next page is requested as soon as fewer than 1 000 bars remain off-screen, pages are chained while you keep panning, comparisons are paginated the same way, and the status bar says **start of history** when the API has returned everything. A transient API error while paginating shows a small *retry* chip; the chart you already have always stays on screen.
40 +
35 41 Equities and ETFs default to the split-and-dividend-adjusted series; the **Adjustment** menu switches to split-only or unadjusted. Continuous futures offer ratio-adjusted, back-adjusted and unadjusted rolls.
36 42
37 −## Series types, indicators, comparisons
43 +## Indicators
44 +
45 +The **Indicators** menu adds an indicator in one click; the **Indicator library** (<kbd>⌘</kbd> <kbd>I</kbd>, or the first entry of that menu) is the full catalogue: search by name, id or description, category tabs — **Favorites, Trend, Momentum, Volatility, Volume, Bands, Support/Resistance, Statistics** — a short description of each indicator, a star to keep your favourites (stored in your browser), and the list of active indicators with reorder / hide / settings / remove.
46 +
47 +Every active indicator has a row in the legend with its values coloured per plot, plus three buttons: **hide** (kept in the URL and the legend, removed from the chart), **⚙ settings** (also on double-click of the row) and **×**. The settings dialog has three tabs and applies every change live:
48 +
49 +| Tab | What you set |
50 +| --- | --- |
51 +| **Inputs** | The form is generated from the indicator's inputs — lengths, multipliers, price source (`close`, `hl2`, `ohlc4`…), anchors, with sliders and bounds. |
52 +| **Style** | Per plot: colour, line width, line style (solid / dashed / dotted), visibility; the levels of oscillators (30 / 70, ±100…). |
53 +| **Visibility** | The timeframes on which the indicator is shown — an intraday-only VWAP, a daily-only 200 SMA. |
54 +
55 +**Reset defaults** restores the catalogue values. Colours follow a fixed 8-colour palette so the same indicator keeps the same colour across symbols unless you override it.
56 +
57 +## Comparisons, series types, scale
38 58
39 59 | Menu | What you get |
40 60 | --- | --- |
41 61 | **Series type** | Candles, hollow candles, OHLC bars, line, area, baseline, Heikin-Ashi, columns, HLC bars. |
42 −| **Indicators** | Overlays — SMA, EMA, WMA, VWAP, Bollinger, Keltner, Donchian, Supertrend, Ichimoku — and oscillators in their own pane — RSI, MACD, Stochastic, ATR, OBV, ADX, CCI, MFI, Volume MA. Each active indicator has a row in the legend: click its name to edit the parameters inline, the **×** removes it. Colours follow a fixed 8-colour palette so the same indicator keeps the same colour across symbols. |
43 −| **Compare** | Overlays other symbols as % change since the first visible bar (the price scale switches to percent while a comparison is active). Chips remove them. |
62 +| **Compare** | Overlays other symbols as % change since the first visible bar (the price scale switches to percent while a comparison is active); each comparison has a **Compare** row in the legend and is paginated like the main series. |
44 63 | **Price scale** | Linear, logarithmic or percent; auto-scale can be turned off after you drag the price axis. |
45 −| **Settings** | Volume histogram, colour-blind mode (hollow candles + a blue / orange palette), watermark, magnet crosshair, reduced motion, and an optional API key kept **in memory only** for this tab. |
64 +| **Settings** | Volume histogram, grid, colour-blind mode (hollow candles + a blue / orange palette), watermark, drawing toolbar, reduced motion, screen-reader announcements, magnet crosshair, "stay in drawing mode", and the multi-chart sync options. |
46 65
47 −The legend always shows the values under the crosshair — or the last bar when the pointer leaves the chart — and the **Table** button opens the same data as an accessible table with a CSV export, so nothing depends on hovering.
66 +The legend always shows the values under the crosshair — or the last bar when the pointer leaves the chart — and the **Table** button opens the same data as an accessible table with a CSV export, so nothing depends on hovering. After every pan or zoom an `aria-live` region describes the visible range (bars, dates, open / close, change, high / low).
48 67
49 68 ## Drawing tools
50 69
51 −The vertical bar on the left holds the drawings: trend line, ray, horizontal and vertical lines, parallel channel, rectangle, Fibonacci retracement, measure, arrow, text and brush. Drawings snap to open / high / low / close when the magnet is on, can be selected, moved and resized, and are saved per symbol and timeframe in your browser.
70 +The vertical bar on the left is organised in groups with flyouts, like a professional terminal: each group button shows the tool you used last in that group (click activates it), the small chevron — or a right-click, or a long press on touch screens — opens the flyout with every tool of the group.
71 +
72 +| Group | Tools |
73 +| --- | --- |
74 +| **Lines** | Trend line, ray, extended line, horizontal ray, horizontal line, vertical line, cross line, parallel channel (2 and 3 points), regression trend, Andrews pitchfork, Schiff pitchfork |
75 +| **Fibonacci &amp; Gann** | Retracement, extension, time zones, fan, arcs, Gann fan, Gann box |
76 +| **Shapes** | Rectangle, ellipse, triangle, polyline, brush, arrow, arrow marker |
77 +| **Text &amp; notes** | Text, callout, price label, flag |
78 +| **Measure &amp; positions** | Measure (Δ price, Δ %, bars, duration), price range, date range, date &amp; price range, vertical range, long position, short position |
79 +| **Patterns** | Elliott impulse wave (12345), Elliott correction wave (ABC), XABCD, head and shoulders |
80 +
81 +Below the groups: **magnet** (snap to open / high / low / close), **stay in drawing mode** (the tool stays armed after each drawing), **hide all**, **lock all**, undo / redo and **remove all**. Selecting a drawing opens a floating properties bar — colour, line width, line style, fill opacity, label text, lock, duplicate, delete — and double-clicking a text opens it for inline editing. Drawings are saved per symbol and timeframe in your browser.
82 +
83 +The **right-click menu** on the chart offers *reset view*, *horizontal line at this price*, *alert line at this price* (a dashed price line with a label), *copy price*, *screenshot*, *table* and *settings*.
84 +
85 +## Bar replay
86 +
87 +The **replay** button (or <kbd>Shift</kbd> <kbd>R</kbd>) rewinds the chart and shows a control bar: play / pause (<kbd>Space</kbd>), step back / forward (<kbd>←</kbd> <kbd>→</kbd>), speed 1× to 10×, a position slider, and **jump to bar** — click the target button then click anywhere on the chart to restart from that bar. Indicators are recomputed on the bars revealed so far, so what you see is exactly what a trader would have seen at that moment. Exit restores the full series.
88 +
89 +## Layouts
90 +
91 +The **layout** menu (or <kbd>Alt</kbd> <kbd>1</kbd> … <kbd>4</kbd>) splits the page into **1**, **2 side by side**, **2 stacked** or **4** charts. Each chart has its own symbol, timeframe, series type and indicators; the toolbar acts on the *active* chart (click a chart to activate it, <kbd>Tab</kbd> cycles). **Settings → Multi-chart sync** synchronises the symbol (change one, all follow), the crosshair and the visible time range between charts. The layout and every chart are in the URL (`layout=2h&s2=MSFT&tf2=1hour`), so a link reproduces the whole workspace.
92 +
93 +## Templates
94 +
95 +The **templates** menu (<kbd>⌘</kbd> <kbd>K</kbd>) saves the current set of indicators with their parameters and styles, the series type, the scale and the volume setting under a name. Apply a template to any chart, mark one as the **default template** — it is applied to charts that open without indicators in the URL and to charts added to a layout — and export / import your templates as JSON to move them between browsers.
96 +
97 +## Keyboard shortcuts
98 +
99 +Press <kbd>?</kbd> for the full panel. The essentials:
52 100
53 101 | Key | Action |
54 102 | --- | --- |
55 −| <kbd>T</kbd> <kbd>H</kbd> <kbd>V</kbd> <kbd>R</kbd> <kbd>F</kbd> <kbd>M</kbd> <kbd>X</kbd> | Trend line · horizontal line · vertical line · rectangle · Fibonacci · measure · text |
56 −| <kbd>Esc</kbd> | Back to the cursor (cancels the current tool) |
57 −| <kbd>Delete</kbd> / <kbd>Backspace</kbd> | Remove the selected drawing |
58 −| <kbd>Ctrl</kbd> <kbd>Z</kbd> · <kbd>Ctrl</kbd> <kbd>Y</kbd> | Undo · redo |
103 +| <kbd>/</kbd> · <kbd>⌘</kbd> <kbd>I</kbd> · <kbd>⌘</kbd> <kbd>K</kbd> · <kbd>?</kbd> | Symbol box · indicator library · templates · shortcuts panel |
104 +| <kbd>T</kbd> <kbd>H</kbd> <kbd>V</kbd> <kbd>C</kbd> <kbd>P</kbd> | Trend line · horizontal line · vertical line · cross line · pitchfork |
105 +| <kbd>F</kbd> <kbd>G</kbd> · <kbd>R</kbd> <kbd>E</kbd> <kbd>B</kbd> <kbd>A</kbd> · <kbd>X</kbd> | Fibonacci · Gann fan · rectangle · ellipse · brush · arrow · text |
106 +| <kbd>M</kbd> · <kbd>L</kbd> <kbd>S</kbd> | Measure · long position · short position |
107 +| <kbd>Esc</kbd> | Back to the cursor (cancels the tool, closes menus) |
108 +| <kbd>Delete</kbd> / <kbd>Backspace</kbd> · <kbd>⌘</kbd> <kbd>D</kbd> | Remove · duplicate the selected drawing |
109 +| <kbd>⌘</kbd> <kbd>Z</kbd> · <kbd>⌘</kbd> <kbd>⇧</kbd> <kbd>Z</kbd> / <kbd>⌘</kbd> <kbd>Y</kbd> | Undo · redo |
110 +| <kbd>Shift</kbd> <kbd>R</kbd> · <kbd>Space</kbd> · <kbd>←</kbd> <kbd>→</kbd> | Replay on / off · play / pause · step |
111 +| <kbd>Alt</kbd> <kbd>1</kbd> … <kbd>4</kbd> · <kbd>Tab</kbd> | Layout · next chart |
59 112 | <kbd>←</kbd> <kbd>→</kbd> · <kbd>+</kbd> <kbd>−</kbd> · <kbd>Home</kbd> <kbd>End</kbd> | Pan · zoom · jump to the oldest / latest bar |
60 −| Wheel · drag · double-click | Zoom around the cursor · pan · fit the whole series |
113 +| Wheel · drag · double-click · right-click | Zoom around the cursor · pan · fit the whole series · context menu |
61 114
62 115 ## Shareable URLs
63 116
64 117 Everything that defines the view lives in the URL, so a link reproduces the chart exactly:
65 118
66 119 ```text
67 −https://www.hfmarketdata.io/charts?s=AAPL&tf=1hour&type=hollow&ind=ema:20,ema:50,rsi:14&cmp=MSFT&scale=log
120 +https://www.hfmarketdata.io/charts?s=AAPL&tf=1hour&type=hollow&ind=ema:20,ema:50,rsi:14&cmp=MSFT&scale=log&layout=2h&s2=ES&asset2=futures
68 121 ```
69 122
70 123 | Parameter | Values |
@@ -78,15 +131,12 @@ https://www.hfmarketdata.io/charts?s=AAPL&tf=1hour&type=hollow&ind=ema:20,ema:50
78 131 | `scale` | `linear` (default), `log`, `percent` |
79 132 | `vol` | `0` hides the volume histogram |
80 133 | `adj` | `adj_split`, `UNADJUSTED`, `contin_UNadj`, `contin_adj_absolute`… |
134 +| `layout` | `2h` (side by side), `2v` (stacked), `4` — then `s2`, `asset2`, `tf2`, `type2`, `ind2`… for the other charts |
81 135
82 136 The **Share** button copies the current URL; **Screenshot** downloads a PNG of the chart with a small attribution.
83 137
84 −## Data limits
138 +## On a phone
85 139
86 −The chart is a regular API client, so the [rate limits](/docs/rate-limits) apply: keyless visitors get 30 requests per hour and at most 5 000 bars per request, a free account 120 requests per minute and 50 000 bars. The first load asks for ~1 500 daily / hourly bars or ~3 000 minute bars (capped by your tier), and each scroll into older history costs one more request — the status bar shows how many requests are left in the window and says **start of history** once the API has returned everything. A 429 is displayed as *rate limited — not down* with a countdown; the chart you already have stays on screen.
87 −
88 −<Callout type="tip" title="Sign in for more history per request">
89 −Signed-in sessions apply your account tier automatically. You can also paste an API key in **Settings** — it stays in memory for this tab only and is never written to storage.
90 −</Callout>
140 +Under 640 px the toolbar keeps the symbol box, the timeframes, a pencil (drawing bar) and **⋯**: everything else — series type, indicators and the library, compare, adjustment, scale, layout, templates, replay, settings, table, screenshot, fullscreen, shortcuts, share — lives in a bottom sheet. Drawing flyouts, the properties bar and the replay controls are bottom sheets / a bottom bar too; a long press on a group button opens its tools.
91 141
92 142 Zero-volume minutes are not in the dataset, so intraday charts have no rows for minutes without a trade; the time axis is indexed by bar, not by wall-clock time, so sessions and weekends leave no gaps — the same convention as professional terminals.
93 143