exchange ulazi u primarni ključ klines tabele; 13.8M redova migrirano. Features dobija kolonu bez PK migracije.
Multi-exchange ready storage. klines i features tabele sada imaju exchange kolonu sa default-om 'binance'. Sanity-check (Faza 5.2) dokazao da je multi-source pooling bezbedan (mean spread < 0.1% vs Binance).
| Exchange | Days overlap | Mean spread vs Binance |
|---|---|---|
| bybit | 365 | 0.006% |
| okx | 300 | 0.006% |
| kraken | 365 | 0.025% |
| binanceus | 365 | 0.078% |
| coinbase | — | (requires apiKey, skipped) |
Svi well below 0.1% threshold. Pool je bezbedan. Detalji u 2026-05-20_faza5_sanity_check.md.
(symbol, interval, open_time) → sada (exchange, symbol, interval, open_time)CREATE TABLE klines_new ... INSERT SELECT 'binance' AS exchange, ... FROM klines ... DROP klines RENAME klines_newexchange TEXT NOT NULL DEFAULT 'binance' (instant, ne menja PK)(symbol, timeframe, close_time) — radi jer je trenutno sve binance(exchange, symbol, timeframe, close_time))Svi 3 cache writers sad propagiraju exchange:
tools/history_cache/build_klines_cache.py:insert_klines — novi parametar exchange='binance'src/klines_provider.py:_write_cache — novi parametar; INSERT INTO sad uključuje exchange kolonu eksplicitnosrc/klines_cache_maintenance.py:_insert_klines — novi parametar; daily catchup i symbol churn propagirajuDefault 'binance' všuda — backward-compatible, postojeće pozive ne traže izmenu.
KlinesProvider.get(symbol, interval, start, end, exchange=None) — novi parametar:
'binance' (iz default_exchange field-a)_read_cache query sad filtrira WHERE exchange = ? first_fetch_from_binance fallback ide samo ako exchange == 'binance' (drugačiji exchange treba CCXTScanner adapter — Faza 5.3)| Symbol | TF | Days | Result |
|---|---|---|---|
| BTCUSDT | 4h | 60 | ✅ identical (360 rows) |
| ETHUSDT | 1h | 7 | ⚠️ 167 vs 168 rows (boundary open-candle leak, pre-existing) |
| SOLUSDT | 15m | 3 | ✅ identical (288 rows) |
| BTCUSDT | 1d | 365 | ✅ identical (365 rows) |
| AAVEUSDT | 4h | 30 | ✅ identical (180 rows) |
4/5 PASS. Jedan fail je boundary issue (provider correctly filtrira open-at-fetch candle, direct path ga uzima). Nije migration regresija.
klines cols: ['exchange', 'symbol', 'interval', 'open_time', 'close_time', ...]
klines PK: ['exchange', 'symbol', 'interval', 'open_time']
klines rows: 13,821,604 (all exchange='binance')
features cols last: 'exchange' (as added column)
features rows: 13,818,805 (all exchange='binance')exchange polje — već implicitno default 'binance'tools/history_cache/migrate_add_exchange.py (klines full migration), inspect_stale, verify_schemareports/analysis/2026-05-20_faza5_sanity_check.mdIzvor: crypto_scanner/reports/analysis/2026-05-20_faza5_schema_migration.md