492b39313a
Trades are intraday (M15/H1) only. D1 stays as a confirmation TF for both so higher-timeframe trend context still gates A/A+ grades. W1 is no longer used anywhere — removes one batch call. Scan now: 3 batch calls (M15, H1, D1) × 7 pairs = 21 credits, ~2 min. Was: 4 batch calls (M15, H1, D1, W1) = 28 credits, ~3 min. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
227 lines
9.1 KiB
Markdown
227 lines
9.1 KiB
Markdown
# ForexBot2 — Engine Logic Reference
|
||
|
||
## 1. Data Provider (Twelve Data API)
|
||
|
||
### What the API provides
|
||
Each API call returns an OHLCV time series for a currency pair:
|
||
|
||
| Field | Description |
|
||
|----------|------------------------------------|
|
||
| Datetime | UTC timestamp of the candle open |
|
||
| Open | Opening price |
|
||
| High | Highest price during the candle |
|
||
| Low | Lowest price during the candle |
|
||
| Close | Closing price |
|
||
| Volume | Tick volume (limited on Forex) |
|
||
|
||
Supported intervals: 1min, 5min, 15min, 30min, 1h, 4h, 1day, 1week.
|
||
|
||
### Supported pairs (free tier — live data)
|
||
EURUSD, GBPUSD, USDJPY, USDCHF, AUDUSD, USDCAD, NZDUSD,
|
||
EURGBP, EURJPY, GBPJPY, AUDJPY, EURCHF, CADJPY.
|
||
All other symbols (XAU, XAG, indices) return no data on the free plan.
|
||
|
||
### API credit limits (free tier)
|
||
- 8 credits per minute
|
||
- 800 credits per day
|
||
- 1 credit per symbol in a batch request
|
||
(7 pairs in one request = 7 credits, not 7 requests)
|
||
|
||
### Data validation and cleaning
|
||
After every fetch the data goes through `_validate_and_clean`:
|
||
1. Drop rows where all of Open/High/Low/Close are NaN
|
||
2. Forward-fill small gaps (max 3 consecutive bars)
|
||
3. Drop rows still missing Close
|
||
4. Remove bars with future timestamps (> 5 min ahead of now)
|
||
5. Fix OHLC inconsistencies (e.g. High < Low) by clamping
|
||
6. Remove extreme outlier bars (> 10 standard deviations return)
|
||
7. Sort index and deduplicate (keep last on duplicates)
|
||
|
||
---
|
||
|
||
## 2. How Many API Calls Are Made
|
||
|
||
### Per scan or /signal command
|
||
|
||
The bot does **one shared prefetch** before spawning TF analyses.
|
||
It collects all unique timeframes needed across scans, then makes
|
||
one batch API call per timeframe (all pairs in a single request).
|
||
|
||
Current SCAN_TIMEFRAMES: M15, H1 (only intraday trade signals)
|
||
Confirmations:
|
||
- M15 uses: H1, D1
|
||
- H1 uses: M15, D1
|
||
|
||
D1 is kept as a confirmation for higher-timeframe trend context but
|
||
no D1 trade signals are produced. W1 has been dropped entirely.
|
||
|
||
Unique timeframes: M15, H1, D1 = **3 batch calls**
|
||
|
||
Each call: 7 pairs × 1 credit = **7 credits per call**
|
||
|
||
Total per scan: **3 calls × 7 credits = 21 credits**
|
||
|
||
With the 8 credits/minute limit:
|
||
- Call 1 (7 credits): fires immediately — 1 credit remaining
|
||
- Call 2 (7 credits): must wait ~60s for window to clear
|
||
- Call 3 (7 credits): waits another ~60s
|
||
|
||
**Minimum scan time: ~2 minutes.**
|
||
|
||
After the shared prefetch, the 4 concurrent TF analyses read from
|
||
the in-memory cache and make **zero additional API calls**.
|
||
|
||
### Cache behaviour
|
||
Results are cached per symbol+timeframe for `refresh_interval` seconds
|
||
(default in PlatformConfig). A second scan within that window skips all
|
||
API calls entirely and returns cached data instantly.
|
||
|
||
---
|
||
|
||
## 3. Technical Engine — How Signals Are Decided
|
||
|
||
### Step 1 — Fetch OHLCV data
|
||
Primary timeframe data is fetched first. If it fails, the report is
|
||
immediately graded F and returned — no further analysis is attempted.
|
||
Confirmation timeframe data is fetched next; failures are logged as
|
||
warnings but do not abort the analysis.
|
||
|
||
### Step 2 — Compute 11 indicators
|
||
|
||
Each indicator returns: value, signal (STRONG_BUY / BUY / NEUTRAL /
|
||
SELL / STRONG_SELL), confidence (0–100), and a weight.
|
||
|
||
| Indicator | Weight | What it measures |
|
||
|------------------|--------|-----------------------------------------------|
|
||
| EMA Trend | 1.2 | Alignment of fast/medium/slow/trend EMAs |
|
||
| MACD | 1.1 | Momentum crossover and histogram direction |
|
||
| Ichimoku | 1.1 | Cloud position, TK cross, cloud colour |
|
||
| RSI | 1.0 | Overbought/oversold momentum |
|
||
| ADX | 1.0 | Trend strength and directional index |
|
||
| Bollinger Bands | 0.9 | Price position within volatility envelope |
|
||
| Stochastic | 0.8 | Oscillator crossover in OB/OS zones |
|
||
| Candlestick | 0.7 | Pattern detection (hammer, engulfing, doji…) |
|
||
| Divergence | 1.5 | RSI/MACD divergence from price (reversal) |
|
||
| Pivot Points | 0.6 | Classical pivot S/R relative to current price |
|
||
| ATR / Volume | 0.0 | Context only — not included in score |
|
||
|
||
Divergence has the highest weight (1.5) because divergences are strong
|
||
reversal predictors. ATR and Volume have weight 0 — they inform the
|
||
trade setup and volatility regime but do not vote on direction.
|
||
|
||
### Step 3 — Classify market regime
|
||
Using ADX value and EMA direction:
|
||
- `trending_up` / `trending_down`: ADX ≥ strong threshold + EMA aligned
|
||
- `ranging`: ADX below threshold
|
||
|
||
The regime changes indicator weights for the composite score:
|
||
- **Trending**: EMA (×1.5), ADX (×1.3), MACD (×1.2) weighted up;
|
||
RSI (×0.7) and Bollinger (×0.6) weighted down
|
||
- **Ranging**: RSI (×1.4), Bollinger (×1.4), Stochastic (×1.3)
|
||
weighted up; EMA (×0.6) and ADX (×0.5) weighted down
|
||
|
||
### Step 4 — Compute composite score (−100 to +100)
|
||
For each indicator:
|
||
```
|
||
weighted_score = signal_value × weight × regime_multiplier × (confidence / 100)
|
||
```
|
||
Signal values: STRONG_BUY = +2, BUY = +1, NEUTRAL = 0, SELL = −1, STRONG_SELL = −2
|
||
|
||
Final composite score = (sum of weighted scores / total weight) × 50
|
||
|
||
Composite signal thresholds:
|
||
- score ≥ +40 → STRONG BUY
|
||
- score ≥ +15 → BUY
|
||
- score ≤ −40 → STRONG SELL
|
||
- score ≤ −15 → SELL
|
||
- otherwise → NEUTRAL
|
||
|
||
### Step 5 — Multi-timeframe (MTF) agreement check
|
||
All timeframe signals (primary + confirmations) are collected.
|
||
MTF agreement = True if at least `mtf_agreement_threshold` timeframes
|
||
all point bullish or all point bearish.
|
||
|
||
Effect on confidence:
|
||
- **Agreement**: confidence +15 (capped at 95); score blended with
|
||
average of all TF scores (60% primary, 40% MTF average)
|
||
- **Disagreement**: confidence ×0.7
|
||
- **Conflict** (some bullish, some bearish): confidence ×0.7 × 0.6 = ×0.42
|
||
+ warning added to report
|
||
|
||
### Step 6 — Fundamental adjustments
|
||
Applied in order, each multiplying confidence:
|
||
|
||
| Condition | Confidence adjustment |
|
||
|----------------------------------|-----------------------|
|
||
| News aligns with technical | +5 (capped 95) |
|
||
| News conflicts with technical | ×0.85 |
|
||
| Event risk: caution | ×0.70 |
|
||
| Event risk: danger | ×0.30 + block signal |
|
||
| Volatility: extreme | ×0.80 |
|
||
|
||
### Step 7 — Final signal determination
|
||
Uses the adjusted score and confidence:
|
||
|
||
| Condition | Signal |
|
||
|----------------------------------|-------------|
|
||
| score ≥ +40 and confidence ≥ 65 | STRONG BUY |
|
||
| score ≥ +15 and confidence ≥ 50 | BUY |
|
||
| score ≤ −40 and confidence ≥ 65 | STRONG SELL |
|
||
| score ≤ −15 and confidence ≥ 50 | SELL |
|
||
| otherwise | NEUTRAL |
|
||
|
||
### Step 8 — Quality grade
|
||
Combines score, confidence, and MTF agreement into a letter grade:
|
||
|
||
| Grade | abs(score) | confidence | MTF agreement |
|
||
|-------|-----------|------------|---------------|
|
||
| A+ | ≥ 50 | ≥ 75 | required |
|
||
| A | ≥ 35 | ≥ 65 | required |
|
||
| B | ≥ 25 | ≥ 55 | not required |
|
||
| C | ≥ 15 | ≥ 45 | not required |
|
||
| D | ≥ 10 | any | not required |
|
||
| F | < 10 | any | — |
|
||
|
||
A+ and A require MTF agreement as a hard condition — no matter how
|
||
strong the primary score, without timeframe alignment the grade caps at B.
|
||
|
||
### Step 9 — Trade setup (grades A+, A, B only)
|
||
Entry = current close price
|
||
Stop Loss = entry ± (ATR × 1.5)
|
||
Take Profit 1 = entry ± (SL distance × R:R ratio)
|
||
Take Profit 2 = entry ± (SL distance × R:R ratio × 1.5)
|
||
|
||
ATR is used as the volatility measure so SL/TP adapt to current
|
||
market conditions rather than using fixed pip distances.
|
||
|
||
---
|
||
|
||
## 4. Signal Flow Summary
|
||
|
||
```
|
||
Telegram /scan or /signal
|
||
│
|
||
▼
|
||
_analyze_all_tfs(pairs)
|
||
│
|
||
├── prefetch_batch(pairs, [M15, H1, D1])
|
||
│ ├── Batch call 1: all pairs @ M15 (7 credits, wait if needed)
|
||
│ ├── Batch call 2: all pairs @ H1 (7 credits, wait if needed)
|
||
│ └── Batch call 3: all pairs @ D1 (7 credits, wait if needed)
|
||
│
|
||
└── 2 threads (M15 + H1), all reading from warm cache
|
||
│
|
||
└── per thread: SignalAggregator.analyze_all_pairs()
|
||
│
|
||
└── per pair: analyze_pair()
|
||
├── fetch_ohlcv (cache hit)
|
||
├── TechnicalEngine.analyze()
|
||
│ ├── 11 indicators
|
||
│ ├── Regime classification
|
||
│ └── Composite score
|
||
├── MTF agreement check
|
||
├── News / event risk adjustments
|
||
├── Final signal + grade
|
||
└── Trade setup (A+/A/B only)
|
||
```
|