feat: add market data architecture and complete migration through build 039

This commit is contained in:
2026-07-14 09:58:16 +03:00
parent 26deb861bc
commit a996f2f797
443 changed files with 80452 additions and 1335 deletions

246
docs/migrations/greps.txt Normal file
View File

@@ -0,0 +1,246 @@
((.venv) ) segeba@mbpbsg dzentra_bot % >....
elif isinstance(data.get("payload"), dict):
payload = data["payload"]
if isinstance(payload.get("symbols"), list):
symbols = payload["symbols"]
print("Количество symbols:", len(symbols) if symbols is not None else None)
if symbols:
dict_items = [item for item in symbols if isinstance(item, dict)]
all_keys = sorted(
{
key
for item in dict_items
for key in item
}
)
print("Все ключи symbol items:")
for key in all_keys:
print(f" {key}")
print("\nПервый symbol item:")
print(json.dumps(dict_items[0], ensure_ascii=False, indent=2))
PY
Корневой тип: dict
Корневые ключи: ['exchangeFilters', 'rateLimits', 'serverTime', 'symbols', 'timezone']
Количество symbols: 51
Все ключи symbol items:
assetType
baseAsset
baseAssetPrecision
country
filters
industry
longRate
marketModes
marketType
maxSLGap
maxTPGap
minSLGap
minTPGap
name
orderTypes
quoteAsset
quoteAssetId
quotePrecision
sector
shortRate
status
swapChargeInterval
symbol
tickSize
tickValue
tradingFee
tradingHours
Первый symbol item:
{
"assetType": "CRYPTOCURRENCY",
"baseAsset": "ETH",
"baseAssetPrecision": 3,
"country": "",
"filters": [
{
"filterType": "LOT_SIZE",
"maxQty": "1000",
"minQty": "0.001",
"stepSize": "0.001"
},
{
"filterType": "MIN_NOTIONAL",
"minNotional": "2"
}
],
"industry": "",
"longRate": -0.01,
"marketModes": [
"REGULAR"
],
"marketType": "LEVERAGE",
"maxSLGap": 50.0,
"maxTPGap": 50.0,
"minSLGap": 0,
"minTPGap": 0,
"name": "ETH/EUR",
"orderTypes": [
"LIMIT",
"MARKET",
"STOP"
],
"quoteAsset": "EUR",
"quoteAssetId": "EUR_LEVERAGE",
"quotePrecision": 3,
"sector": "",
"shortRate": 0.01,
"status": "TRADING",
"swapChargeInterval": 480,
"symbol": "ETH/EUR_LEVERAGE",
"tickSize": 0.01,
"tickValue": 18.3415,
"tradingFee": 0.06,
"tradingHours": "UTC; Mon - 21:00, 21:05 -; Tue - 21:00, 21:05 -; Wed - 21:00, 21:05 -; Thu - 21:00, 21:05 -; Fri - 21:00, 22:01 -; Sat - 05:00, 07:00 - 21:00, 21:05 -; Sun - 21:00, 21:05 -"
}
((.venv) ) segeba@mbpbsg dzentra_bot % >....
filter_keys: dict[str, set[str]] = {}
for item in symbols:
if not isinstance(item, dict):
continue
filters = item.get("filters")
if not isinstance(filters, list):
continue
for entry in filters:
if not isinstance(entry, dict):
continue
filter_type = str(entry.get("filterType") or "<missing>")
filter_types[filter_type] += 1
filter_keys.setdefault(filter_type, set()).update(
str(key) for key in entry
)
print("Типы filters:")
for filter_type, count in sorted(filter_types.items()):
print(f"{filter_type}: {count}")
print(" keys:", sorted(filter_keys[filter_type]))
PY
Типы filters:
LOT_SIZE: 51
keys: ['filterType', 'maxQty', 'minQty', 'stepSize']
MIN_NOTIONAL: 39
keys: ['filterType', 'minNotional']
python - <<'PY'
import json
from collections import Counter
from pathlib import Path
path = Path(
"app/tools/dzengi_probe/runtime_samples/rest/exchangeInfo/all.json"
)
data = json.loads(path.read_text(encoding="utf-8"))
if isinstance(data, dict) and isinstance(data.get("symbols"), list):
symbols = data["symbols"]
elif (
isinstance(data, dict)
and isinstance(data.get("payload"), dict)
and isinstance(data["payload"].get("symbols"), list)
):
symbols = data["payload"]["symbols"]
else:
raise SystemExit("symbols не найдены")
fields = [
"symbol",
"name",
"status",
"baseAsset",
"quoteAsset",
"marketModes",
"marketType",
"tickSize",
"stepSize",
"minQty",
"minNotional",
"filters",
]
for field in fields:
present = 0
non_empty = 0
types = Counter()
for item in symbols:
if not isinstance(item, dict):
continue
if field in item:
present += 1
value = item[field]
types[type(value).__name__] += 1
if value not in (None, "", [], {}):
non_empty += 1
print(
f"{field}: present={present}, "
f"non_empty={non_empty}, "
f"types={dict(types)}"
)
PY
symbol: present=51, non_empty=51, types={'str': 51}
name: present=51, non_empty=51, types={'str': 51}
status: present=51, non_empty=51, types={'str': 51}
baseAsset: present=51, non_empty=51, types={'str': 51}
quoteAsset: present=51, non_empty=51, types={'str': 51}
marketModes: present=51, non_empty=51, types={'list': 51}
marketType: present=51, non_empty=51, types={'str': 51}
tickSize: present=51, non_empty=51, types={'float': 48, 'int': 3}
stepSize: present=0, non_empty=0, types={}
minQty: present=0, non_empty=0, types={}
minNotional: present=0, non_empty=0, types={}
filters: present=51, non_empty=51, types={'list': 51}
((.venv) ) segeba@mbpbsg dzentra_bot % ;2B
((.venv) ) segeba@mbpbsg dzentra_bot % ;2Bgrep -RIn \
--exclude-dir="__pycache__" \
--exclude="*.pyc" \
-E "from src\.telegram\.handlers\.market import|import src\.telegram\.handlers\.market|include_router\(.*market|market\.router|handlers\.market" \
app/src app/tests tests 2>/dev/null
((.venv) ) segeba@mbpbsg dzentra_bot % grep -RIn \
--exclude-dir="__pycache__" \
--exclude="*.pyc" \
-E "include_router|include_routers" \
app/src \
| grep -Ei "market|router"
app/src/telegram/routers.py:16: dispatcher.include_router(start_router)
app/src/telegram/routers.py:17: dispatcher.include_router(home_router)
app/src/telegram/routers.py:18: dispatcher.include_router(portfolio_router)
app/src/telegram/routers.py:19: dispatcher.include_router(auto_router)
app/src/telegram/routers.py:20: dispatcher.include_router(journal_router)
app/src/telegram/routers.py:21: dispatcher.include_router(debug_auto_router)
app/src/telegram/routers.py:22: dispatcher.include_router(debug_router)
app/src/telegram/routers.py:23: dispatcher.include_router(system_router)
app/src/telegram/handlers/auto/__init__.py:8:router.include_router(main_router)
app/src/telegram/handlers/auto/__init__.py:9:router.include_router(risk_router)
((.venv) ) segeba@mbpbsg dzentra_bot %
((.venv) ) segeba@mbpbsg dzentra_bot % grep -RIn \
--exclude-dir="__pycache__" \
--exclude="*.pyc" \
-E "from src\.telegram\.ui\.currency_ui import|import src\.telegram\.ui\.currency_ui" \
app/src app/tests tests 2>/dev/null
app/src/telegram/handlers/market.py:28:from src.telegram.ui.currency_ui import format_usd_amount
app/src/telegram/handlers/portfolio.py:26:from src.telegram.ui.currency_ui import (