Add hub-only OKX amp stats for ETH/BTC session windows.
Read-only 1H index candles, point amplitude metrics, history save and CSV export; no order-path changes. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
"""振幅统计历史作业存储(中控 JSON)."""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import threading
|
||||
import uuid
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
from typing import Any, Optional
|
||||
|
||||
_LOCK = threading.Lock()
|
||||
_STORE_NAME = "amp_stats_history.json"
|
||||
_MAX_ITEMS = 80
|
||||
|
||||
|
||||
def _store_path() -> Path:
|
||||
return Path(__file__).resolve().parent / _STORE_NAME
|
||||
|
||||
|
||||
def _now_iso() -> str:
|
||||
return datetime.now(timezone.utc).astimezone().strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
|
||||
def _load() -> dict[str, Any]:
|
||||
path = _store_path()
|
||||
if not path.is_file():
|
||||
return {"items": []}
|
||||
try:
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
except Exception:
|
||||
return {"items": []}
|
||||
if not isinstance(data, dict):
|
||||
return {"items": []}
|
||||
items = data.get("items")
|
||||
if not isinstance(items, list):
|
||||
items = []
|
||||
return {"items": items}
|
||||
|
||||
|
||||
def _save(data: dict[str, Any]) -> None:
|
||||
path = _store_path()
|
||||
path.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8")
|
||||
|
||||
|
||||
def list_history(*, symbol: str = "", limit: int = 50) -> list[dict[str, Any]]:
|
||||
with _LOCK:
|
||||
items = list(_load().get("items") or [])
|
||||
sym = (symbol or "").strip().lower()
|
||||
if sym:
|
||||
items = [x for x in items if str(x.get("symbol") or "").lower() == sym]
|
||||
limit = max(1, min(200, int(limit or 50)))
|
||||
out = []
|
||||
for it in items[:limit]:
|
||||
out.append(
|
||||
{
|
||||
"id": it.get("id"),
|
||||
"created_at": it.get("created_at"),
|
||||
"symbol": it.get("symbol"),
|
||||
"symbol_label": it.get("symbol_label"),
|
||||
"start_hour": it.get("start_hour"),
|
||||
"end_hour": it.get("end_hour"),
|
||||
"period": it.get("period"),
|
||||
"price_source": it.get("price_source"),
|
||||
"sample_count": (it.get("summary") or {}).get("sample_count"),
|
||||
"max_amplitude": (it.get("summary") or {}).get("max_amplitude"),
|
||||
"max_amplitude_day": (it.get("summary") or {}).get("max_amplitude_day"),
|
||||
}
|
||||
)
|
||||
return out
|
||||
|
||||
|
||||
def get_history(item_id: str) -> Optional[dict[str, Any]]:
|
||||
iid = (item_id or "").strip()
|
||||
if not iid:
|
||||
return None
|
||||
with _LOCK:
|
||||
for it in _load().get("items") or []:
|
||||
if str(it.get("id")) == iid:
|
||||
return dict(it)
|
||||
return None
|
||||
|
||||
|
||||
def save_history(payload: dict[str, Any]) -> dict[str, Any]:
|
||||
item = {
|
||||
"id": uuid.uuid4().hex[:12],
|
||||
"created_at": _now_iso(),
|
||||
"exchange": payload.get("exchange"),
|
||||
"symbol": payload.get("symbol"),
|
||||
"symbol_label": payload.get("symbol_label"),
|
||||
"start_hour": payload.get("start_hour"),
|
||||
"end_hour": payload.get("end_hour"),
|
||||
"period": payload.get("period"),
|
||||
"timeframe": payload.get("timeframe"),
|
||||
"price_source": payload.get("price_source"),
|
||||
"inst_id": payload.get("inst_id"),
|
||||
"timezone": payload.get("timezone"),
|
||||
"summary": payload.get("summary") or {},
|
||||
"rows": payload.get("rows") or [],
|
||||
"missing_count": payload.get("missing_count") or 0,
|
||||
}
|
||||
with _LOCK:
|
||||
data = _load()
|
||||
items = list(data.get("items") or [])
|
||||
items.insert(0, item)
|
||||
data["items"] = items[:_MAX_ITEMS]
|
||||
_save(data)
|
||||
return item
|
||||
|
||||
|
||||
def delete_history(item_id: str) -> bool:
|
||||
iid = (item_id or "").strip()
|
||||
if not iid:
|
||||
return False
|
||||
with _LOCK:
|
||||
data = _load()
|
||||
items = list(data.get("items") or [])
|
||||
new_items = [x for x in items if str(x.get("id")) != iid]
|
||||
if len(new_items) == len(items):
|
||||
return False
|
||||
data["items"] = new_items
|
||||
_save(data)
|
||||
return True
|
||||
Reference in New Issue
Block a user