Signal Workflow
Crypto Signal AI processes each market snapshot through a fixed pipeline: fetch candles, compute indicators, generate strategy signals, score them, apply risk checks, persist results, alert optionally, and track outcomes over time.
Workflow Steps
During a scan, the app loops over every configured symbol and timeframe. All strategies run on the same candle data. Each strategy signal then moves through scoring, risk approval, persistence, and optional alerting as an individual record. Outcome tracking runs separately on stored signals when you update outcomes or run watch mode.
Market Candles
The scanner loads price candles from the configured exchange for each symbol and timeframe pair. This is the only market input used before any strategy logic runs.
- Exchange, symbols, and timeframes come from your configuration.
- Fresh candles are loaded from the exchange before each scan or watch cycle.
- The same candle set is reused for every strategy on that symbol and timeframe.
Indicators + Regime
Technical indicators are calculated from the candles, then the latest bar is classified into a market regime that strategies use for context.
- Indicators include EMA, RSI, MACD, ATR, Bollinger Bands, ADX, and volume change.
- Regime classification covers trend direction, trend strength, and volatility state.
- Indicator values and regime are stored with every strategy signal for transparency.
Strategy Signal
Each enabled strategy reviews the candles and may produce a signal with entry, stop loss, take profit, and strategy-specific reasons.
- Strategies run independently on the same symbol and timeframe.
- A strategy signal includes direction (long or short), price levels, reward-to-risk, and indicator values.
- Duplicate signals for the same setup are skipped if already stored.
AI / Rule Scoring
Every strategy signal is scored and explained. When an OpenAI API key is configured, an AI model evaluates the setup; otherwise a built-in rule engine scores it.
- Output includes score (0–1), decision (pass or reject), explanation, and conflicts.
- Rule-based scoring checks regime alignment, RSI extremes, volume confirmation, and R:R.
- Cross-strategy conflicts are added when multiple strategies fire on the same market snapshot.
Risk Approval
Hard risk limits are applied before a signal is treated as approved. Rejected signals are still stored with reasons.
- Checks daily signal cap, AI rejection, minimum reward-to-risk (1.0), and maximum stop distance.
- Approved signals receive a suggested position size based on your account equity and risk settings.
- Signal strength is set from the AI score; status becomes approved or rejected.
Database + Alerts
Final signals are saved to the database and optionally sent to Telegram or Discord when alerts are enabled.
- Each record stores prices, AI evaluation, approval status, sizing, and risk reasons.
- Scan output can also be printed to the terminal for review.
- Alerts include entry, stop, target, strength, explanation, and conflict notes.
Outcome Tracking
After a signal is stored, later candles are checked to see whether price reached take profit, stop loss, or expired without resolution.
- Outcomes start as pending and are updated by the outcomes command or watch loop.
- Resolution uses candles after the signal, up to your configured bar limit.
- Final states: take profit, stop loss, or expired.
Stored Signal Data
Inside the pipeline, each strategy first produces a strategy signal. The system then enriches it with AI scoring, risk approval, and position sizing to produce a final signal. These detailed records are saved for review and may appear in terminal scan output — they are not the same as the short alert messages sent to Telegram or Discord.
Strategy Signal
Direct output from a strategy — prices, indicators, regime, and trigger reasons — before AI scoring, risk checks, or saving.
| Field | Description |
|---|---|
symbol | Trading pair (e.g. BTC/USDT) |
timeframe | Candle interval (e.g. 4h) |
strategy | Strategy name (e.g. ema_rsi_breakout) |
side | Trade direction: long or short |
entry | Suggested entry price |
stop_loss | Stop-loss price |
take_profit | Take-profit price |
risk_reward | Reward-to-risk ratio |
indicators.rsi | RSI value at signal time |
indicators.ema_20 | 20-period EMA |
indicators.ema_50 | 50-period EMA |
indicators.ema_200 | 200-period EMA |
indicators.macd | MACD line value |
indicators.macd_signal | MACD signal line value |
indicators.atr | Average True Range |
indicators.volume_change | Current volume vs 20-bar average |
indicators.bb_upper | Bollinger Band upper band |
indicators.bb_lower | Bollinger Band lower band |
indicators.bb_width | Bollinger Band width relative to price |
indicators.atr_percentile | ATR percentile over recent bars |
indicators.adx | Average Directional Index |
regime_analysis | Market regime context: primary label, trend strength, volatility state, compression, confidence, reasons, and summary |
regime_analysis.regime | Primary regime label (uptrend, downtrend, ranging, high_volatility, unknown) |
regime_analysis.summary | One-line human-readable regime explanation |
regime_analysis.confidence | How confident the classifier is (0–1), based on indicator availability and signal strength |
regime_analysis.reasons | Why this regime was assigned (ADX, ATR percentile, EMA stack, etc.) |
reasons | Strategy-specific trigger reasons |
timestamp | UTC time the signal was generated |
Example strategy signal from EMA RSI Breakout on BTC/USDT 4h:
{
"symbol": "BTC/USDT",
"timeframe": "4h",
"strategy": "ema_rsi_breakout",
"side": "long",
"entry": 64250.0,
"stop_loss": 63810.5,
"take_profit": 65129.0,
"risk_reward": 2.0,
"indicators": {
"rsi": 58.4,
"ema_20": 64120.0,
"ema_50": 63980.0,
"ema_200": 63100.0,
"macd": 125.3,
"macd_signal": 98.7,
"atr": 293.0,
"volume_change": 1.35,
"bb_upper": 64800.0,
"bb_lower": 63450.0,
"bb_width": 0.021,
"atr_percentile": 0.62,
"adx": 28.5
},
"regime_analysis": {
"regime": "uptrend",
"trend_strength": "strong",
"volatility": "normal",
"volatility_percentile": 0.62,
"compression": false,
"confidence": 0.85,
"reasons": [
"ADX 28.50 indicates strong trend strength",
"ATR percentile 0.62 indicates normal volatility",
"Price is above EMA20 and EMA50 with sufficient trend strength"
],
"summary": "uptrend (85% confidence) — strong trend — normal volatility"
},
"reasons": [
"EMA 20 above EMA 50",
"RSI recovered above 50",
"MACD crossed above signal line"
],
"timestamp": "2026-06-24T12:00:00"
}Final Signal
The complete record after scoring and risk approval. Both approved and rejected signals are saved. The record id and peer signal fields are added when the signal is stored.
| Field | Description |
|---|---|
raw | The original strategy output (see Strategy Signal above) |
ai.score | AI or rule-based confidence score (0–1) |
ai.decision | Scoring decision: pass or reject |
ai.explanation | Human-readable evaluation summary |
ai.conflicts | Detected conflicts with regime, indicators, or other strategies |
ai.model | Model used for scoring (e.g. gpt-4o-mini or rule-based) |
status | Approval status: approved or rejected |
strength | Signal strength, set from AI score (0–1) |
position_size.account_equity | Account equity used for sizing |
position_size.risk_pct | Risk fraction per trade |
position_size.risk_amount | Dollar amount at risk |
position_size.stop_distance | Absolute distance from entry to stop loss |
position_size.stop_pct | Stop distance as a fraction of entry |
position_size.suggested_quantity | Suggested position size in base units |
position_size.suggested_notional | Suggested position value in quote currency |
risk_reasons | Why the signal was approved or rejected |
id | Stored record id (added after saving) |
peer_signals | Other strategies that fired on the same symbol and timeframe |
opposing_strategies_on_market | Whether long and short signals exist in the same batch |
Example final signal after an approved setup is processed:
{
"raw": {
"symbol": "BTC/USDT",
"timeframe": "4h",
"strategy": "ema_rsi_breakout",
"side": "long",
"entry": 64250.0,
"stop_loss": 63810.5,
"take_profit": 65129.0,
"risk_reward": 2.0,
"indicators": {
"rsi": 58.4,
"ema_20": 64120.0,
"ema_50": 63980.0,
"ema_200": 63100.0,
"macd": 125.3,
"macd_signal": 98.7,
"atr": 293.0,
"volume_change": 1.35,
"bb_upper": 64800.0,
"bb_lower": 63450.0,
"bb_width": 0.021,
"atr_percentile": 0.62,
"adx": 28.5
},
"regime_analysis": {
"regime": "uptrend",
"trend_strength": "strong",
"volatility": "normal",
"volatility_percentile": 0.62,
"compression": false,
"confidence": 0.85,
"reasons": [
"ADX 28.50 indicates strong trend strength",
"ATR percentile 0.62 indicates normal volatility",
"Price is above EMA20 and EMA50 with sufficient trend strength"
],
"summary": "uptrend (85% confidence) — strong trend — normal volatility"
},
"reasons": [
"EMA 20 above EMA 50",
"RSI recovered above 50",
"MACD crossed above signal line"
],
"timestamp": "2026-06-24T12:00:00"
},
"ai": {
"score": 0.78,
"decision": "pass",
"explanation": "Setup aligns with uptrend regime. EMA stack is bullish, RSI shows recovery without being overbought, and volume confirms the move.",
"conflicts": [],
"model": "gpt-4o-mini"
},
"status": "approved",
"strength": 0.78,
"position_size": {
"account_equity": 10000.0,
"risk_pct": 0.02,
"risk_amount": 200.0,
"stop_distance": 439.5,
"stop_pct": 0.00684,
"suggested_quantity": 0.45506371,
"suggested_notional": 29237.84
},
"risk_reasons": [
"Signal passed risk checks"
],
"id": 42,
"peer_signals": [],
"opposing_strategies_on_market": false
}Alert Signals
When alerts are enabled, each final signal is formatted into a human-readable message and sent to Telegram or Discord. This is what you receive in chat — a condensed summary, not the full stored record. Both approved and rejected signals are sent.
How to Read Alerts
Telegram and Discord deliver the same content — only text formatting differs. Read top to bottom: start with the header to see whether the signal passed and which market it applies to, then check the trade levels, scan the explanation and reasons, and review risk notes or conflicts before acting.
| Field | Description |
|---|---|
Header — APPROVED / REJECTED | Risk manager outcome. APPROVED means the signal passed daily caps, minimum R:R, stop distance, and AI checks. REJECTED means it was logged but failed one or more checks — still sent if alerts are on. |
Header — symbol & timeframe | The market and candle interval the signal was generated on (e.g. BTC/USDT on 4h). |
Header — LONG / SHORT | Suggested trade direction from the strategy. |
Strategy | Which strategy detected the setup (e.g. EMA RSI Breakout). See the Strategies page for what each one looks for. |
Entry | SL | TP | Suggested entry price, stop-loss, and take-profit levels calculated by the strategy. SL is where the setup is invalidated; TP is the reward target. |
R:R | Reward-to-risk ratio — how much profit is targeted relative to the stop distance. The system requires at least 1.0. |
Strength | Confidence score from 0 to 1, set from the AI or rule-based evaluation. Higher values mean the scorer found fewer issues with the setup. |
AI pass / reject | Whether the AI or rule engine accepted the setup before risk checks. A signal can show AI pass but still be REJECTED if risk limits fail. |
Suggested size | Optional position-sizing hint based on your account equity and max risk per trade. Shows base units, total notional in quote currency, and dollar amount at risk if the stop is hit. |
Explanation (italic) | Plain-language summary from the AI or rule scorer explaining why the setup looks good or weak. |
Reasons | Bullet list of strategy-specific triggers that caused the signal (e.g. EMA cross, RSI recovery). |
Risk | Why the signal was approved or rejected by the risk manager (e.g. passed checks, AI rejected, daily cap reached). |
Conflicts | Optional section listing contradictions the scorer found — regime mismatch, bearish indicators on a long, or opposing strategies on the same market. Omitted when there are none. |
Quick checklist when a message arrives:
- Status — Is it APPROVED or REJECTED? Rejected alerts are informational; they tell you what the system filtered out and why.
- Direction — LONG or SHORT on the symbol and timeframe shown in the header.
- Levels — Entry, stop-loss (SL), and take-profit (TP) define the trade plan.
- Quality — Strength, AI decision, explanation, and Conflicts (if present) show how confident the system is.
- Sizing — Suggested size is a starting point based on your configured equity and risk — adjust to your own account and rules.
Telegram
Requires Telegram bot token and chat ID in your configuration. Sent with Telegram Markdown — single asterisks for bold, backticks for inline values.
*APPROVED* — *BTC/USDT* (4h) — LONG
Strategy: `ema_rsi_breakout`
Entry: `64250.0000` | SL: `63810.5000` | TP: `65129.0000`
R:R `2.00` | Strength `0.78` | AI `pass`
Suggested size: `0.455064` units | notional `29237.84` | risk `200.00`
_Setup aligns with uptrend regime. EMA stack is bullish, RSI shows recovery without being overbought, and volume confirms the move._
Reasons:
• EMA 20 above EMA 50
• RSI recovered above 50
• MACD crossed above signal line
Risk:
• Signal passed risk checksDiscord
Requires a Discord webhook URL in your configuration. Uses the same message with single asterisks replaced by double asterisks for Discord Markdown bold formatting.
**APPROVED** — **BTC/USDT** (4h) — LONG
Strategy: `ema_rsi_breakout`
Entry: `64250.0000` | SL: `63810.5000` | TP: `65129.0000`
R:R `2.00` | Strength `0.78` | AI `pass`
Suggested size: `0.455064` units | notional `29237.84` | risk `200.00`
_Setup aligns with uptrend regime. EMA stack is bullish, RSI shows recovery without being overbought, and volume confirms the move._
Reasons:
• EMA 20 above EMA 50
• RSI recovered above 50
• MACD crossed above signal line
Risk:
• Signal passed risk checks