1. Context & Goal
Project: Egis – private mobile-first trading system
Stack: Laravel 12, Inertia + React, shadcn/ui, Binance Futures Testnet
Core rule: Internal positions table is the single source of truth
Goal of this phase:
- Introduce a new strategy Signal Hook
- Accept trading signals from external platforms
- Automatically place orders with:
- Correct sizing (respect bot budget)
- Correct side (long / short)
- Proper Stop Loss (SL) and Take Profit (TP)
- Maintain system safety, auditability, and determinism
2. Signal Hook Strategy (Design Decision)
Strategy definition
- New strategy:
signal_hook - Required field on bot:
signal_key - A bot using this strategy listens for external signals via webhook
Why
- Decouple signal generation from execution
- Allow TradingView / custom systems to trigger Egis bots
- Keep execution logic centralized and controlled
3. Signal Hook Webhook Design
Endpoint
POST /api/signal-hook
Payload format (wrapper required)
{
"payloads": {
"signal_key": "ZEN_PULSE_1MIN",
"symbol": "AVNTUSDT.P",
"side": "long",
"price": "1.245",
"stop_loss": "1.180",
"take_profit": "1.360"
}
}
Key rules
payloadswrapper is mandatoryprice,stop_loss,take_profit:- Accepted as strings
- Must represent numeric values
- Converted to decimals internally
symbolnormalization:- If ends with
.P→ strip suffix "AVNTUSDT.P"→"AVNTUSDT"
- If ends with
- No CSRF (API route only)
4. Persistence: signal_hook_events
Every request is stored — no exceptions
Stored fields include:
bot_id(nullable)signal_keysymbol(normalized)sideprice,stop_loss,take_profit(decimal)status:invalid | rejected | accepted | failed | processederror_messageraw_payloadprocessed_at- Result metadata (exchange order IDs, messages)
Reasoning
- Webhooks are external and unreliable
- Storage-first allows replay, debugging, and audit
- Execution must never depend on ephemeral requests
5. Execution Flow (Signal → Order)
Step 1: Receive & Validate
- Validate wrapper + payload
- Resolve bot by
signal_key - Strategy must be
signal_hook - Store event
- If accepted → dispatch job
Step 2: Job — PlaceOrderFromSignalHookEvent
Job responsibilities:
- Load signal event
- Ensure:
status = acceptedprocessed_at = null
- Load bot and exchange connection
- Compute order size safely
- Place entry order
- Confirm fill
- Place SL & TP orders
- Persist results
6. Critical Bug #1 — Wrong Order Size ($100 vs $10)
Symptom
- Bot budget:
$10 - Order placed:
$100
Root Cause
- Signal Hook job used:
- Hardcoded default size
- Or fallback not tied to available budget
Fix
- Signal Hook job must:
- Compute available budget from internal positions
- Clamp order size:
requested_size_usd <= available_budget - If budget ≤ 0 → do not place order
Lesson
Signal-driven automation must NEVER bypass risk/budget logic used by manual trading.
7. Critical Bug #2 — SL / TP Not Placed
Symptom
- Entry order placed successfully
- No SL / TP orders appear on Binance
Investigation
- Compared Egis implementation with previous working system (Samir)
- Found SL/TP logic:
- Either not executed
- Or using incorrect Binance params
- Or exiting early after entry fill
Correct Binance Futures Pattern (from Samir)
Important Binance rule
MARKET entry + SL/TP must be two-step
Correct flow
- Place ENTRY order (MARKET)
- Confirm fill (executed qty > 0)
- Place protective orders:
- STOP / STOP_MARKET (SL)
- TAKE_PROFIT / TAKE_PROFIT_MARKET (TP)
- Must be:
reduceOnlyorclosePosition=true- Correct side mapping
Side mapping
| Position | SL / TP Order Side |
|---|---|
| LONG | SELL |
| SHORT | BUY |
Key mistake
- SL/TP code path was never reached after fill confirmation
- Or parameters didn’t match Binance Futures expectations
Lesson
Protective orders are not “configuration”; they are separate, explicit actions.
8. Debugging Method Used (Important)
Instead of guessing:
- Read real logs
storage/logs/laravel.log - Search for:
- Entry order success
- SL / TP placement attempts
- Binance errors
- Add explicit logs:
- “Placing SL”
- “Placing TP”
- Final signed params (signature redacted)
- Binance responses
Lesson
If it’s not in logs, it didn’t happen.
9. Safety & Architecture Principles Reinforced
- Internal
positionsis always authoritative - Exchange tables are derived and repairable
- Orders are immutable facts
- No “delete order”
- Jobs must be idempotent
- External success ≠ internal success
- Store → then execute → then protect
10. Key Takeaways (For Future Rebuild)
- Webhook systems must be storage-first
- Signal ≠ execution
- Budget logic must be centralized
- SL/TP must be explicit, post-fill actions
- Never trust default sizing
- Logs are the real truth
- If it worked before, diff against the working system
