-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path02_watchlist_triage.py
More file actions
83 lines (63 loc) · 2.92 KB
/
Copy path02_watchlist_triage.py
File metadata and controls
83 lines (63 loc) · 2.92 KB
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
"""Triage a watchlist: what fired, and how much of it is worth reading.
Prints the styled table and then the subset that actually clears its baseline.
python examples/02_watchlist_triage.py
python examples/02_watchlist_triage.py AAPL MSFT NVDA TSLA
"""
from __future__ import annotations
import sys
from honest_signals import check_watchlist, print_report
from honest_signals.stats import Verdict
DEFAULT_WATCHLIST = ["AAPL", "MSFT", "NVDA", "SPY", "QQQ", "BTCUSDT", "ETHUSDT"]
def main() -> int:
tickers = sys.argv[1:] or DEFAULT_WATCHLIST
report = check_watchlist(tickers, timeframe="1d", within_bars=5)
print_report(report, show_disclaimer=False)
unmeasured = [s for s in report.signals if s.verdict is Verdict.NO_BASELINE]
if unmeasured:
print()
print(
f"{len(unmeasured)} of {len(report.signals)} signals came back with a hit rate "
"but no baseline, so their edge is unmeasured rather than absent."
)
actionable = [s for s in report.ranked() if s.verdict.is_actionable]
print()
if not actionable:
print("Nothing on this watchlist clears its own baseline today.")
print("That is the normal outcome, not a failure of the tool: across the")
print("105 (pattern, timeframe, confidence-band) cells measured on 2026-07-18,")
print("only three separated from their baseline -- all three on crypto, and")
print("fewer than the ~5.3 that chance alone would produce. On US stocks &")
print("ETFs it was 0 of 60. Exactly one of the 105 landed ABOVE its baseline")
print("(double_top 1d 0.50-0.75, +9.78pp on n=149), and none of the three")
print("survives a correction for having tested 105 cells.")
return 0
print(f"{len(actionable)} of {len(report.signals)} signals separate from their baseline:")
print()
for signal in actionable:
verb = "clears" if signal.verdict is Verdict.BEATS_BASELINE else "trails"
lift = signal.lift
assert lift is not None
print(
f" {signal.ticker:<9} {signal.pattern:<20} {verb:<7} "
f"{lift.lift_pp:+.1f}pp vs {lift.baseline:.1%} baseline "
f"(n={signal.sample_size:,}, {signal.bars_ago} bars ago)"
)
trailing = [s for s in actionable if s.verdict is Verdict.TRAILS_BASELINE]
if trailing:
print()
print(
f"Note: {len(trailing)} of these did WORSE than no pattern at all, "
"by more than the interval on the difference allows for."
)
print()
print(
"Before acting on any of these: a handful of nominal findings is what you "
"expect from scanning many cells. Ask whether the count exceeds chance."
)
if report.errors:
print()
for symbol, message in report.errors.items():
print(f"skipped {symbol}: {message}")
return 0
if __name__ == "__main__":
raise SystemExit(main())