File size: 1,588 Bytes
67ec045
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5badb6f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import math
import pathlib
import sys

sys.path.append(str(pathlib.Path(__file__).resolve().parents[1]))

from app import compute_signal, futures_pnl, recommend_position_size


def _mock_data(n=60, start=1900.0, step=0.2):
    t = list(range(1, n + 1))
    c = [start + i * step for i in range(n)]
    o = [x - 0.2 for x in c]
    h = [x + 0.4 for x in c]
    l = [x - 0.4 for x in c]
    v = [1000 + i for i in range(n)]
    return {"t": t, "o": o, "h": h, "l": l, "c": c, "v": v}


def test_futures_pnl_long():
    out = futures_pnl(side="LONG", entry=1900, exit_price=1902, contracts=2)
    assert out["points"] == 2
    assert out["gross_pnl_vnd"] > 0


def test_recommend_position_size_non_negative():
    out = recommend_position_size(price=1900, atr=2.0, account_balance=100_000_000)
    assert out["contracts"] >= 0
    assert out["risk_per_contract"] > 0


def test_compute_signal_shape():
    out = compute_signal(_mock_data())
    assert out["signal"] in {"BUY", "SELL", "HOLD", "WAIT"}
    assert isinstance(out["confidence"], float)
    assert "reason" in out


def test_compute_signal_wait_when_short_history():
    out = compute_signal(_mock_data(n=20))
    assert out["signal"] == "WAIT"
    assert "Warming up" in out["reason"]


def test_compute_signal_risk_when_actionable():
    out = compute_signal(_mock_data(n=80, start=1800, step=0.5))
    if out["signal"] in {"BUY", "SELL", "HOLD"}:
        # HOLD can still carry risk object in current design.
        assert "risk" in out
        if out["risk"] is not None:
            assert math.isfinite(out["risk"]["atr"])