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.

FieldDescription
symbolTrading pair (e.g. BTC/USDT)
timeframeCandle interval (e.g. 4h)
strategyStrategy name (e.g. ema_rsi_breakout)
sideTrade direction: long or short
entrySuggested entry price
stop_lossStop-loss price
take_profitTake-profit price
risk_rewardReward-to-risk ratio
indicators.rsiRSI value at signal time
indicators.ema_2020-period EMA
indicators.ema_5050-period EMA
indicators.ema_200200-period EMA
indicators.macdMACD line value
indicators.macd_signalMACD signal line value
indicators.atrAverage True Range
indicators.volume_changeCurrent volume vs 20-bar average
indicators.bb_upperBollinger Band upper band
indicators.bb_lowerBollinger Band lower band
indicators.bb_widthBollinger Band width relative to price
indicators.atr_percentileATR percentile over recent bars
indicators.adxAverage Directional Index
regime_analysisMarket regime context: primary label, trend strength, volatility state, compression, confidence, reasons, and summary
regime_analysis.regimePrimary regime label (uptrend, downtrend, ranging, high_volatility, unknown)
regime_analysis.summaryOne-line human-readable regime explanation
regime_analysis.confidenceHow confident the classifier is (0–1), based on indicator availability and signal strength
regime_analysis.reasonsWhy this regime was assigned (ADX, ATR percentile, EMA stack, etc.)
reasonsStrategy-specific trigger reasons
timestampUTC 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.

FieldDescription
rawThe original strategy output (see Strategy Signal above)
ai.scoreAI or rule-based confidence score (0–1)
ai.decisionScoring decision: pass or reject
ai.explanationHuman-readable evaluation summary
ai.conflictsDetected conflicts with regime, indicators, or other strategies
ai.modelModel used for scoring (e.g. gpt-4o-mini or rule-based)
statusApproval status: approved or rejected
strengthSignal strength, set from AI score (0–1)
position_size.account_equityAccount equity used for sizing
position_size.risk_pctRisk fraction per trade
position_size.risk_amountDollar amount at risk
position_size.stop_distanceAbsolute distance from entry to stop loss
position_size.stop_pctStop distance as a fraction of entry
position_size.suggested_quantitySuggested position size in base units
position_size.suggested_notionalSuggested position value in quote currency
risk_reasonsWhy the signal was approved or rejected
idStored record id (added after saving)
peer_signalsOther strategies that fired on the same symbol and timeframe
opposing_strategies_on_marketWhether 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.

FieldDescription
Header — APPROVED / REJECTEDRisk 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 & timeframeThe market and candle interval the signal was generated on (e.g. BTC/USDT on 4h).
Header — LONG / SHORTSuggested trade direction from the strategy.
StrategyWhich strategy detected the setup (e.g. EMA RSI Breakout). See the Strategies page for what each one looks for.
Entry | SL | TPSuggested 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:RReward-to-risk ratio — how much profit is targeted relative to the stop distance. The system requires at least 1.0.
StrengthConfidence 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 / rejectWhether 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 sizeOptional 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.
ReasonsBullet list of strategy-specific triggers that caused the signal (e.g. EMA cross, RSI recovery).
RiskWhy the signal was approved or rejected by the risk manager (e.g. passed checks, AI rejected, daily cap reached).
ConflictsOptional 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 checks

Discord

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