feat(web): 增量自动刷新、结构区修复与默认指标/周期
自动刷新常态只拉 recent 尾部 K,每 1 分钟全量重算缠论;修复结构区缓存导入;默认指标/4h·1h·15m/近30天;同步 ECR-009 screener 相关改动。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -31,6 +31,8 @@ def test_wyckoff_crypto_page_ok(client):
|
||||
resp = client.get("/wyckoff_crypto")
|
||||
assert resp.status_code == 200
|
||||
assert b"Crypto Wyckoff Screener" in resp.data
|
||||
assert b"fCombo" in resp.data
|
||||
assert b"chartCanvas" in resp.data
|
||||
|
||||
|
||||
def test_wyckoff_crypto_meta_ok(client):
|
||||
@@ -38,11 +40,84 @@ def test_wyckoff_crypto_meta_ok(client):
|
||||
assert resp.status_code == 200
|
||||
data = resp.get_json()
|
||||
assert "engine_version" in data
|
||||
assert data.get("timeframes") == ["1d", "1w", "1M"]
|
||||
assert data.get("combo", {}).get("id") == "h8_4_1"
|
||||
assert data["combo"]["low"] == "1h"
|
||||
ids = {c["id"] for c in data.get("combos") or []}
|
||||
assert "h8_4_1" in ids and "d_w_m" in ids
|
||||
|
||||
|
||||
def test_wyckoff_crypto_scan_ok(client):
|
||||
resp = client.get("/api/wyckoff_crypto/scan?limit=5")
|
||||
resp = client.get("/api/wyckoff_crypto/scan?limit=5&combo_id=h8_4_1")
|
||||
assert resp.status_code == 200
|
||||
data = resp.get_json()
|
||||
assert "rows" in data
|
||||
assert data.get("combo", {}).get("id") == "h8_4_1"
|
||||
|
||||
|
||||
def test_wyckoff_crypto_klines_bad_request(client):
|
||||
resp = client.get("/api/wyckoff_crypto/klines")
|
||||
assert resp.status_code == 400
|
||||
|
||||
|
||||
def test_wyckoff_crypto_klines_ok(client):
|
||||
resp = client.get(
|
||||
"/api/wyckoff_crypto/klines?symbol=BTC/USDT:USDT&tf=1h&limit=10&combo_id=h8_4_1"
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
data = resp.get_json()
|
||||
assert "items" in data
|
||||
assert data.get("tf") == "1h"
|
||||
assert data.get("intraday") is True
|
||||
if data["items"]:
|
||||
assert "datetime" in data["items"][0]
|
||||
assert "ts" in data["items"][0]
|
||||
assert "T" in data["items"][0]["datetime"]
|
||||
assert "+08:00" in data["items"][0]["datetime"]
|
||||
|
||||
|
||||
def test_wyckoff_crypto_klines_bad_limit_ok(client):
|
||||
resp = client.get(
|
||||
"/api/wyckoff_crypto/klines?symbol=BTC/USDT:USDT&tf=1h&limit=abc&combo_id=h8_4_1"
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
|
||||
|
||||
def test_wyckoff_crypto_overlay_ok(client):
|
||||
resp = client.get(
|
||||
"/api/wyckoff_crypto/overlay?symbol=BTC/USDT:USDT&tf=1h&bars=60&combo_id=h8_4_1"
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
data = resp.get_json()
|
||||
assert "phases" in data
|
||||
assert "events" in data
|
||||
|
||||
|
||||
def test_combos_add_and_list(client, tmp_path, monkeypatch):
|
||||
from crypto_wyckoff import combos as cm
|
||||
|
||||
monkeypatch.setattr(cm, "_COMBOS_FILE", tmp_path / "combos.json")
|
||||
monkeypatch.setattr(cm, "_cache", None)
|
||||
|
||||
resp = client.get("/api/wyckoff_crypto/combos")
|
||||
assert resp.status_code == 200
|
||||
assert len(resp.get_json()["combos"]) >= 2
|
||||
|
||||
bad = client.post(
|
||||
"/api/wyckoff_crypto/combos",
|
||||
json={"high": "1h", "mid": "4h", "low": "8h"},
|
||||
)
|
||||
assert bad.status_code == 400
|
||||
|
||||
ok = client.post(
|
||||
"/api/wyckoff_crypto/combos",
|
||||
json={"high": "12h", "mid": "4h", "low": "1h", "label": "12h/4h/1h"},
|
||||
)
|
||||
assert ok.status_code == 200
|
||||
cid = ok.get_json()["combo"]["id"]
|
||||
assert cid == "12h_4h_1h"
|
||||
|
||||
deleted = client.delete(f"/api/wyckoff_crypto/combos/{cid}")
|
||||
assert deleted.status_code == 200
|
||||
|
||||
builtin = client.delete("/api/wyckoff_crypto/combos/h8_4_1")
|
||||
assert builtin.status_code == 400
|
||||
|
||||
Reference in New Issue
Block a user