koala73 / koala73/worldmonitor
feat(markets): add Russian equities + IMOEX via MOEX ISS API
- Dominant language
- TypeScript
- Stars
- 86.6k
- Forks
- 13.1k
- Avg merge
- 8h 4m
- Merged PRs (30d)
- 825
Description
Split out of #6146 (1 of 3 on the Russia/China market-data thread).
## Gap
We have **zero** Russian market data. MOEX exists in the codebase only as static chrome:
- `src/config/finance-geo.ts:87` — a pin on the exchange map
- `src/components/WorldClockPanel.ts:22` — a market-hours clock
No quotes, no index, no instruments. `IMOEX` and Russian equities are absent from `scripts/shared/stocks.json`.
## Source: MOEX ISS
`https://iss.moex.com/iss` — free, **no key, no registration**, 15-minute delayed. Probed live on 2026-08-04, both 200:
```
GET /iss/engines/stock/markets/index/securities/IMOEX.json?iss.meta=off
→ 200, 1297B, application/json; charset=utf-8
→ ["IMOEX","SNDX","Индекс МосБиржи",2,"Индекс МосБиржи",3014.21,1898.51,"RUB","PR"]
(SECID, BOARDID, NAME, DECIMALS, SHORTNAME, ANNUALHIGH, ANNUALLOW, CURRENCYID, CALCMODE)
GET /iss/engines/stock/markets/shares/boards/TQBR/securities.json?iss.meta=off&iss.only=marketdata
→ 200, 203359B
→ columns: SECID, BOARDID, BID, BIDDEPTH, OFFER, OFFERDEPTH, SPREAD, ..., OPEN, LOW, HIGH, LAST, LASTCHANGE, LASTCHANGEPRCNT, QTY
```
This is the cleanest of the three sources in #6146: **UTF-8 JSON**, no encoding or number-format traps (contrast the CBR issue, which has both).
## Scope
- Add `IMOEX` to the market-quotes surface. The board endpoint also gives the full Russian equity market if we want per-name coverage.
- ISS returns a columnar `{columns: [...], data: [[...]]}` shape — zip by column name, never by positional index, so a column insertion upstream can't silently shift every field.
## Landmine: payload size
The `TQBR` board response is **203KB** raw. Cap it — and per the established seam in this repo, cap in `publishTransform`, **not** in the fetcher, so `extraKeys` consumers still see the full fetched set. Same pattern as the existing bounded-payload seeders.
## Not in scope
Per-user Russian access routing. These are server-side seeders — a user in Russia reads `worldmonitor.app`, not MOEX directly. This issue is about **coverage** (we publish no Russian market data at all), which is a different problem from the one #6146's title describes.
Contributor guide
Research direction
Locate the existing market-data seeders and their bounded-payload publishTransform pattern, then inspect the MOEX ISS IMOEX and TQBR board responses described here. Preserve column-name mapping and keep the fetcher's full result available to extraKeys consumers. Done means Russian market data is published, with the payload cap applied at publishTransform.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- backend, data
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100