Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 11 additions & 14 deletions Signal Generators/SL Hunting AI Agent/premarket_note.json
Original file line number Diff line number Diff line change
@@ -1,30 +1,27 @@
{
"for_date": "2026-08-14",
"source": "Intraday Hunter, 'Prediction For 14 AUG 2026' (MhmlrlUEUGI, uploaded 2026-08-13)",
"context": "No decisive crowd anywhere. BankNIFTY made little momentum with buyers and sellers at the SAME price level; Sensex ran both ways. The market held its round number and recovered, so sellers are unlikely to have carried overnight.",
"for_date": "2026-08-17",
"source": "Intraday Hunter, 'Prediction For 17 AUG 2026' (4xfMmQW6x5I, uploaded 2026-08-16)",
"context": "All three indices recovered after sellers were removed or stopped out, leaving buyers as the likely seated crowd. The sell-side plan targets those buyers, but a gap-down can recruit fresh sellers and increase risk.",
"plan": [
"FLAT to GAP-DOWN: identify SELL-side setups. On Sensex the reason is explicit -- target the BUYERS, since the market has sat on support since yesterday and the sellers did not hold.",
"GAP-UP: go WITH the market and identify BUY-side setups. On BankNIFTY 'the buyer becomes safe' there, so there is nothing left to hunt on that side.",
"NOBODY IS DECISIVELY SEATED -- on BankNIFTY 'buyers and sellers would be sitting at the SAME price level', and on Sensex claiming either side is seated 'would be WRONG'. This is the empty-book condition.",
"His mechanism for that condition, worth keeping: 'where the crowd is THIN, that is where the market tries to make momentum.' Thin is not dead -- the move goes where there is least resistance.",
"He PREFERS a gap to a flat open: 'better it is not flat -- either a gap-up or a gap-down.' A flat open 'extracts a small momentum and goes away', producing nothing worth trading.",
"There is little pressure on BankNIFTY's sellers, so the market cannot target them directly. The flat/gap-down branch is therefore a FOLLOW of the drift, not a seller hunt."
"GAP-UP or FLAT: identify confirmed SELL-side setups targeting the buyers left seated after the prior recovery.",
"GAP-DOWN: retain the SELL-side search, but risk is higher because fresh sellers may participate; the gap alone is not confirmation.",
"GAP-DOWN WITH POSITIVE MOMENTUM: a large recovery weakens the short plan. Retain it only if the recovery stays limited and the normal setup confirms."
],
"levels": [
{
"index": "NIFTY",
"resistance": [24440, 24540],
"support": [24275, 24176]
"support": [24300, 24210]
},
{
"index": "BANKNIFTY",
"resistance": [57890, 58000],
"support": [57500, 57320]
"resistance": [57720, 57890],
"support": [57280, 57154]
},
{
"index": "SENSEX",
"resistance": [78145, 78500],
"support": [77500, 77200]
"resistance": [78300, 78500],
"support": [77700, 77400]
}
]
}
106 changes: 106 additions & 0 deletions Signal Generators/SL Hunting AI Agent/sl_hunting_doc.md
Original file line number Diff line number Diff line change
Expand Up @@ -3465,3 +3465,109 @@ Test updated: `test_shipped_note_matches_august_14_intraday_hunter_plan`
replaces the 13 Aug equivalent and asserts both branch directions plus the
thin-crowd mechanism and the gap-over-flat preference, because those two are
what a summarising edit would drop first.

---

## Video addendum - the 14 Aug LIVE SESSION (v4h)

**Source:** Intraday Hunter live session `H7RXIw5xbZk` (14 Aug 2026, 12:18).

A WIN, and unusually it is a win **held through a full drawdown** rather than one
that went straight to target. That is what makes it useful: every previous
version in this series learned from either a clean win or a clean loss, so the
prompt had no worked example of a correct trade that looked wrong in the middle.

### The two rules that shipped

**ENTRY QUALITY AND DIRECTION ARE SEPARATE JUDGEMENTS.** A trade that ends green
does not retroactively make its entry good, and a trade that goes immediately
against you was not necessarily the wrong side. Without this split, the journal
teaches the agent to grade its reads by their P&L, which is exactly the feedback
loop that produces revenge entries after a stopped-out correct call.

**THE LOSS LIMIT IS A PERMISSION TO WAIT.** This one is the reason the version
exists, and it is also the most dangerous line in the prompt if read alone -
"permission to wait" one careless paraphrase away from "hold losers". It is
bounded on both sides in the prose and both bounds are test-asserted: the limit
licenses patience *toward* the stop, never *past* it, and it forbids cutting
inside it on feel. It explicitly names v4e's `DISCIPLINE IS ASYMMETRIC` as the
rule it refines rather than overrides.

The one thing allowed to override that patience is elapsed time, so v4g's
time-shrinks-the-target rule was extended rather than left to contradict it:
time does not merely shrink the payoff, it **EXPIRES THE PREMISE**. IH, booking
out: "time has become quite a lot, gradually other people will start
participating." Waiting to the limit is right while the premise holds; elapsed
time can retire the premise before price ever reaches the limit.
`test_v4h_entry_and_direction_and_the_loss_limit_pair_with_their_neighbours`
asserts the reconciliation in both directions.

### One rule was cut for budget, not for merit

A third rule - **A SEATED CROWD IS WARNED BEFORE IT IS HUNTED, SO NO WARNING
MEANS NO CROWD** - was written, tested, and then removed to fit the cap. IH:
"if sellers WERE seated, the market would go up to target them - especially to
give a WARNING... because the market kept making no momentum, sellers will not
be seated, so it will not go up to warn." The mechanism is that an early adverse
spike is the market shaking a seated crowd, so its *absence* confirms an empty
book. It is the sharpest new idea in the session and it should be the first
thing restored once a pruning pass frees room.

### Knowledge changes (v4h, all prose)

- `RISK`: ENTRY QUALITY AND DIRECTION ARE SEPARATE JUDGEMENTS; THE LOSS LIMIT IS
A PERMISSION TO WAIT.
- `RISK` (extended): TIME SPENT IN THE TRADE ... now also EXPIRES THE PREMISE.
- **Pruned:** v4e's `A SHARP FIRST SLIDE BAITS; A SLOW ONE MEANS IT` - superseded
by v4f's confirmation rule, which covers the same tell with a checkable trigger.
- Prompt size 111,283 -> 112,730 chars. **Assembled 114,021 against a 114,140
budget - 119 chars of headroom.** The cap is now the binding constraint on this
series: v4i cannot ship anything without pruning first. See below.

### The budget is now the design constraint

Worst-case runtime additions (12 lessons x 280 + a 2,500-char note) are already
reserved, so the true ceiling for static prose is 114,140 assembled. At 119 chars
of slack, the append-only rhythm this series has used since v3 is finished.
Before v4i, someone should do a dedicated pruning pass over `OPENING_DRIVE` and
`RISK` - both have accumulated rules that later versions restated with better
triggers - and re-measure. That is a knowledge-quality task and deserves its own
change, not a rushed trim at the end of a version.

### How our agent traded the same session

Realized: **-3,854.50** across 47 legs.

| Strategy | Legs | Realized |
|---|---|---|
| SL Hunting AI | 2 | **+2,866.50** |
| **Total** | **47** | **-3,854.50** |

**SL Hunting was the best strategy on the board for the second consecutive day**,
cross-checked against its own `Result summary` (+2,866.50, Trades=2).

| Time | Decision | Reason |
|---|---|---|
| 10:04 | ENTER_LONG | `flush_reversal_hammer_confirmed` |
| 10:07 | EXIT | `double_top_rejection_premise_fade` |
| 10:20 | ENTER_SHORT | `double_top_bearish_engulfing_breakdown` |

**Agent vs IH.** Both finished on the same side - IH put-side/short, the agent
short from 10:20 - and both booked on a partial rather than a full target. The
agent got there by a different route: it took a long first, released it three
minutes later on a premise fade, and reversed. That reversal is the behaviour
v4f's confirmation rule was written to produce, and it is worth noting that the
10:07 exit was a *premise* exit on a trade that was not yet losing - which is the
disciplined half of the rule v4h now bounds from the other side.

Two trades is again a small sample, and the basket was negative regardless. The
signal worth keeping is narrower than "the agent is good now": across 12, 13 and
14 Aug, every SL Hunting exit had a **nameable** reason, and the two profitable
days are the two where that was true.

### Operational note

The supervisor heartbeat shipped in the session-state work is confirmed working
in production: **65 heartbeat lines** in the 14 Aug log. The 2026-08-12 failure
mode - snapshot writes stopping silently at 12:30 while trading continued to
15:10 - would now be visible within five minutes.
35 changes: 27 additions & 8 deletions Signal Generators/SL Hunting AI Agent/sl_hunting_knowledge.py
Original file line number Diff line number Diff line change
Expand Up @@ -565,14 +565,15 @@
v4c's WHEN THE TRAPPED INVENTORY IS SPENT, THE MARKET MANUFACTURES MORE:
manufacturing is what the market does over time, but it may not complete inside
your holding period, and you cannot bank on being early to it.
- A SHARP FIRST SLIDE BAITS; A SLOW ONE MEANS IT (v4e). IH's read of the opening
move, stated as a prior: "if it had fallen SLOWLY I would even have accepted that
the market might produce a big move. But the selling was SHARP — the market
suddenly offered greed", i.e. an abrupt drop looks engineered to recruit sellers,
whereas a grinding one looks like genuine supply. Treat this as a weak prior and
nothing more: on the very session that produced it, the sharp slide was followed
by continuous selling and the bait read was WRONG. Use it to break a tie between
two otherwise-equal reads, never as the premise of a trade on its own.
- ENTRY QUALITY AND DIRECTION ARE SEPARATE JUDGEMENTS (v4h). IH, entering a fall
he knew might reverse: "if the market turns it could go much higher — then we
would be wrong ACCORDING TO DIRECTION. We would NOT be wrong according to
ENTRY... if it is going to go up anyway, you could enter here, or here, or here
— in all three there would be a loss."
A loss decomposes into two independent errors needing different fixes: a bad
ENTRY means a better price existed and was missed (timing); a bad DIRECTION
means no entry price would have helped (read). Score them separately, and never
let a good entry launder a wrong read, or a wrong read condemn a good entry.
- THE CHART DOES NOT REPEAT TWO DAYS RUNNING (v4f). When today's open reproduces
yesterday's shape — same flat open, same immediate drop, same indices — that
SAMENESS is itself the tell, and it argues AGAINST the continuation everyone
Expand Down Expand Up @@ -1110,6 +1111,17 @@
Operationally: an exit needs a NAMED, checkable reason — stop, target, the
profit rate falling, the premise invalidated, the round number crossed, the
time cutoff. "It might turn" is not on that list.
- THE LOSS LIMIT IS A PERMISSION TO WAIT, NOT ONLY A PLACE TO STOP (v4h). Read
this WITH v4e's DISCIPLINE IS ASYMMETRIC, not against it: that rule says cut a
loser mechanically, this one says cut it AT the limit and not before, because
cutting early is its own error. IH, deep in a drawdown that later paid: "in ANY
situation, do NOT cut the trade where you feel your position can still be saved.
If the position has gone wrong but the loss LIMIT is still pending, we wait...
many traders, when the opposite momentum comes, cut the loss BEFORE the limit."
Its two shapes: running after the breakout because surely nothing falls now, and
holding the first adverse leg but running on the SECOND. Same error, different
depths. So the limit is two-sided — it forbids holding past it, AND forbids
cutting inside it on feel. Only the rule below legitimately overrides it.
- TIME SPENT IN THE TRADE SHRINKS THE ACHIEVABLE TARGET (v4g). Elapsed time is a
cost in its own right, separate from price. A trade that stalls and round-trips
does not merely return to where it started — it returns with less of the
Expand All @@ -1121,6 +1133,13 @@
So when a trade consumes materially more time than the read assumed, SHRINK
the target rather than extending the wait — especially on an expiry session,
where premium is draining while you wait.
Extended (v4h): time does not merely shrink the payoff, it EXPIRES THE PREMISE.
"With more time the STRUCTURE changes — the seller/buyer situation changes", and
later, booking out: "time has become quite a lot, gradually other people will
start participating." The crowd you entered against is not the crowd still there
an hour on. This is what overrides the loss-limit patience above: waiting to the
limit is right while the premise holds, and elapsed time can retire the premise
before price ever reaches the limit.
- NEVER EXIT AT ZERO AFTER A GOOD PROFIT HAS PRINTED (v4g). Once meaningful open
profit has actually appeared on the screen, the floor for that trade stops
being breakeven and becomes "some profit". IH, booking a reduced winner: "we
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,17 +201,15 @@ def test_shipped_note_targets_the_next_TRADING_day_not_the_next_calendar_day():
)


def test_shipped_note_matches_august_14_intraday_hunter_plan():
"""The committed advisory must match the hand-checked 13 Aug transcript.
def test_shipped_note_matches_august_17_intraday_hunter_plan():
"""The committed advisory must match the hand-checked 16 Aug transcript.

This catches a stale prior-session note, an inverted gap plan, or a mistyped
chart level before the dated note is injected into the live prompt.

What distinguishes this one is that NEITHER side is seated -- he says so for
both BankNIFTY ("the same price level") and Sensex ("would be WRONG" to
claim either). That is the empty-book condition v4f describes, so the note
carries his own mechanism for it (thin crowd -> that is where momentum
goes) rather than letting the agent infer a seated crowd that is not there.
What distinguishes this session is the same sell-side search across gap-up,
flat, and gap-down opens, with an explicit extra-risk test for a gap-down:
fresh sellers or a large positive recovery can make the buyer hunt unsafe.
"""
import os

Expand All @@ -220,37 +218,33 @@ def test_shipped_note_matches_august_14_intraday_hunter_plan():
note = load_premarket_note(shipped)

assert note is not None
assert note.for_date == "2026-08-14"
assert "MhmlrlUEUGI" in note.source
# The distinguishing fact: no decisive crowd on either side.
assert "SAME price level" in note.context
assert note.plan[0].startswith("FLAT to GAP-DOWN: identify SELL-side setups")
assert note.plan[1].startswith("GAP-UP: go WITH the market")
assert any("NOBODY IS DECISIVELY SEATED" in line for line in note.plan)
# The thin-crowd mechanism and the explicit preference for a gap over a flat
# open are the two ideas a summarising edit would drop first.
assert any("where the crowd is THIN" in line for line in note.plan)
assert any("PREFERS a gap to a flat open" in line for line in note.plan)
assert len(note.plan) == 6
assert note.for_date == "2026-08-17"
assert "4xfMmQW6x5I" in note.source
assert "buyers as the likely seated crowd" in note.context
assert note.plan == [
"GAP-UP or FLAT: identify confirmed SELL-side setups targeting the "
"buyers left seated after the prior recovery.",
"GAP-DOWN: retain the SELL-side search, but risk is higher because fresh "
"sellers may participate; the gap alone is not confirmation.",
"GAP-DOWN WITH POSITIVE MOMENTUM: a large recovery weakens the short plan. "
"Retain it only if the recovery stays limited and the normal setup confirms.",
]
assert [level.model_dump() for level in note.levels] == [
{
"index": "NIFTY",
# 24176 was READ OFF THE CHART, not inferred. The auto-caption
# rendered it "2476" on both 13 and 14 Aug; a 1080p frame at 2:04
# shows the teal support line labelled 24,176.20, alongside
# 24,275.25 and resistances at 24,443.85 / 24,540.85 -- every one
# matching what he speaks. Prefer this method over omitting a level.
"resistance": [24440.0, 24540.0],
"support": [24275.0, 24176.0],
"support": [24300.0, 24210.0],
},
{
"index": "BANKNIFTY",
"resistance": [57890.0, 58000.0],
"support": [57500.0, 57320.0],
# The auto-caption garbles the second support. The chart frame at
# 0:44 labels the two selected teal levels 57,280 and 57,154.
"resistance": [57720.0, 57890.0],
"support": [57280.0, 57154.0],
},
{
"index": "SENSEX",
"resistance": [78145.0, 78500.0],
"support": [77500.0, 77200.0],
"resistance": [78300.0, 78500.0],
"support": [77700.0, 77400.0],
},
]
Original file line number Diff line number Diff line change
Expand Up @@ -878,7 +878,10 @@ def test_system_prompt_has_v4e_recruitment_and_losing_session_knowledge():
prompt = build_system_prompt()
assert "WHICH CROWD THE OPEN RECRUITS DECIDES HOW BIG THE TRAP IS" in prompt
assert "A FORECAST OF WHO WILL ARRIVE IS NOT EVIDENCE OF WHO IS SEATED" in prompt
assert "A SHARP FIRST SLIDE BAITS; A SLOW ONE MEANS IT" in prompt
# v4e's A SHARP FIRST SLIDE BAITS was PRUNED in v4h: it shipped as a weak
# prior with its own counter-example attached, and v4h's warning-move rule
# covers the same ground with an observable mechanism. See the v4h addendum.
assert "A SHARP FIRST SLIDE BAITS" not in prompt
assert "NAME THE LAST POINT, NOT ONLY THE STOP" in prompt
assert "DISCIPLINE IS ASYMMETRIC BETWEEN WINNERS AND LOSERS" in prompt
# The recruitment distinction is the point; both halves must be present.
Expand All @@ -901,11 +904,34 @@ def test_v4e_empty_book_is_a_no_trade_not_a_forecasting_licence():
# It must also reconcile with v4c rather than silently contradicting it.
assert "MANUFACTURES MORE" in section

# And the bait prior must stay a tie-breaker, never a standalone premise.
bait = prompt[prompt.index("A SHARP FIRST SLIDE BAITS"):]
bait = bait[: bait.index("\n- ")] if "\n- " in bait else bait
assert "weak prior" in bait
assert "never as the premise of a trade on its own" in bait

def test_v4h_entry_and_direction_and_the_loss_limit_pair_with_their_neighbours():
"""v4h (14 Aug live session): a win held through a full drawdown.

Two of its rules sit directly on top of earlier ones and would be dangerous
read alone, so both reconciliations are asserted here.
"""
prompt = build_system_prompt()
# The prose is hard-wrapped, so a phrase this test cares about can straddle a
# line break. Collapse whitespace before asserting on wording -- otherwise the
# test breaks on a re-wrap that changed nothing about what the agent reads.
flat = " ".join(prompt.split())
assert "ENTRY QUALITY AND DIRECTION ARE SEPARATE JUDGEMENTS" in flat
assert "THE LOSS LIMIT IS A PERMISSION TO WAIT" in flat

# The loss-limit rule must not read as "hold losers": it is bounded on BOTH
# sides, and it has to name the v4e rule it refines rather than contradict.
limit = prompt[prompt.index("THE LOSS LIMIT IS A PERMISSION TO WAIT"):]
limit = " ".join((limit[: limit.index("\n- ")] if "\n- " in limit else limit).split())
assert "DISCIPLINE IS ASYMMETRIC" in limit
assert "not against it" in limit
assert "forbids holding past it" in limit
assert "forbids" in limit and "cutting inside it" in limit

# Elapsed time is the one thing allowed to override that patience, and the
# time rule has to say so or the two become contradictory advice.
assert "EXPIRES THE PREMISE" in flat
assert "retire the premise before price ever reaches the limit" in flat


def test_system_prompt_has_v4f_repeat_chart_and_confirmation_knowledge():
Expand Down