How to Add Real-Time Orderflow Intelligence to Your Freqtrade Bot in 10 Lines of Python

posted Originally published at dev.to 6 min read

How to Add Real-Time Orderflow Intelligence to Your Freqtrade Bot in 10 Lines of Python

Stop letting RSI lie to your bot. Here's how to give it actual market intelligence.


The Problem Every Freqtrade User Knows

You've tuned your strategy. The backtests look great. You go live — and your bot walks straight into a trap.

The RSI said oversold. The EMA said buy. Everything looked perfect.

But something in the orderbook was screaming danger — and your bot had no way to hear it.


What Actually Happened

I ran a live experiment: I fed the same market data to both traditional indicators and a real-time L2 orderbook analyzer simultaneously, then recorded what each one saw.

Here's the exact 60-second timeline on BTCUSDT:

Time Orderflow Signal RSI What Was Happening
22:03:40 BUY_PRESSURE / delta_accel: 0.4 43 Institutional buying detected
22:03:49 SELL_PRESSURE / delta_accel: 10.4 43 26x selling spike — RSI silent
22:03:57 NEUTRAL / delta_accel: 2.37 43 Absorption phase begins
22:04:15 BUY_PRESSURE / delta_accel: 0.05 43 Buyers returning

RSI stayed at 43 the entire time.

While a complete institutional selling cycle — spike, absorption, recovery — happened in the orderbook, the indicator that millions of bots rely on did not move a single point.

This is not a bug. This is how lagging indicators work by design.


The Fix: Pre-Entry Orderflow Confirmation

The solution isn't to replace your strategy. It's to add one layer of reality-checking before any order is submitted.

Freqtrade has a perfect hook for this: confirm_trade_entry().

This function is called exactly once, right before Freqtrade submits a buy order. If it returns False, the trade is blocked. If it returns True, execution proceeds.

Here's the complete integration:

Step 1: Install

pip install horus-flow-mcp requests

Get your free API key at RapidAPI — Horus Flow Intelligence

Step 2: The Connector (save as horus_connector.py)

import requests
import logging
from typing import Optional

logger = logging.getLogger("HorusConnector")

class HorusConnector:
    """
    Pre-trade orderflow filter for Freqtrade.
    Blocks entries when institutional orderflow is adversarial.
    Fail-OPEN: if API is unreachable, trade proceeds normally.
    """

    DANGER_SIGNALS = {
        "SELL_PRESSURE",
        "LIQUIDITY_EVENT",
        "EMERGENCY_DUMP",
        "BAILOUT"
    }

    ENTRY_SIGNALS = {
        "BUY_PRESSURE",
        "BUY_ABSORPTION"   # Strongest signal: whales absorbing sell pressure
    }

    def __init__(self, api_key: str, min_confidence: float = 0.70):
        self.min_confidence = min_confidence
        self.headers = {
            "x-rapidapi-key": api_key,
            "x-rapidapi-host": "horus-flow-intelligence.p.rapidapi.com"
        }
        self.base_url = "https://horus-flow-intelligence.p.rapidapi.com"

    def is_safe_to_enter(self, symbol: str) -> bool:
        """
        Returns True only when orderflow confirms favorable conditions.
        Returns True on API failure (fail-open = don't block on network issues).
        """
        symbol = symbol.replace("/", "").upper()

        try:
            response = requests.get(
                f"{self.base_url}/v1/flow/crypto/{symbol}",
                headers=self.headers,
                timeout=2
            )
            data = response.json()

            signal = data.get("signal", "NEUTRAL")
            confidence = data.get("confidence", 0)
            flags = data.get("metrics", {}).get("flags", [])

            # Hard block: dangerous market conditions
            if signal in self.DANGER_SIGNALS:
                logger.info(f"[Horus ] {symbol} blocked — {signal} ({confidence:.0%})")
                return False

            # Hard block: spoofing detected regardless of signal
            if any("SPOOFING_DETECTED" in f for f in flags):
                logger.info(f"[Horus ] {symbol} blocked — Spoofing: {flags}")
                return False

            # Green light: confirmed institutional buy-side activity
            if signal in self.ENTRY_SIGNALS and confidence >= self.min_confidence:
                logger.info(f"[Horus ✅] {symbol} confirmed — {signal} ({confidence:.0%})")
                return True

            # Gray zone: neutral or low conviction
            logger.info(f"[Horus ⏳] {symbol} waiting — {signal} ({confidence:.0%})")
            return False

        except Exception:
            # Network issue: fail-open, let Freqtrade decide
            return True

Step 3: Add to Your Strategy (10 lines)

import os
from horus_connector import HorusConnector
from freqtrade.strategy import IStrategy
from pandas import DataFrame

class HorusFilteredStrategy(IStrategy):
    """
    Any existing strategy + Horus orderflow pre-entry confirmation.
    Replace populate_indicators/entry/exit with your own logic.
    """

    timeframe = "5m"
    minimal_roi = {"0": 0.03}
    stoploss = -0.02

    # Initialize Horus — reads key from environment variable
    horus = HorusConnector(
        api_key=os.getenv("RAPIDAPI_KEY", ""),
        min_confidence=0.70
    )

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # Your existing indicator logic here
        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # Your existing entry conditions here
        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # Your existing exit conditions here
        return dataframe

    def confirm_trade_entry(self, pair: str, **kwargs) -> bool:
        """
        ← This is the only addition to your existing strategy.
        Horus checks the live orderbook before every single entry.
        If orderflow is adversarial, the trade is blocked.
        """
        return self.horus.is_safe_to_enter(pair)

Step 4: Run

export RAPIDAPI_KEY="your_key_here"
freqtrade trade --strategy HorusFilteredStrategy --dry-run

What This Does in Practice

Your bot's existing logic still generates entry signals. Nothing changes there.

The only difference: before Freqtrade submits the order, it now asks one additional question — "What is the live orderbook actually saying right now?"

If the answer is SELL_PRESSURE, LIQUIDITY_EVENT, or SPOOFING_DETECTED, the trade is blocked.
If the answer is BUY_PRESSURE or BUY_ABSORPTION with sufficient confidence, execution proceeds.
If the answer is NEUTRAL or low confidence, the system waits.

Here's what the logs look like:

[Horus ✅] ETHUSDT confirmed — BUY_ABSORPTION (90%)
[Horus ] BTCUSDT blocked — SELL_PRESSURE (85%)
[Horus ] SOLUSDT blocked — Spoofing detected
[Horus ⏳] ADAUSDT waiting — NEUTRAL (60%)

What Selective Filtering Looks Like in Practice

In a typical live session, the system scans thousands of assets continuously. Of all the technical signals generated, only a small fraction pass the orderflow confirmation layer.

This low pass-rate is not a bug — it's the filter working correctly.

Most market conditions are not suitable for entry. A bot that knows when not to trade is more valuable than one that trades constantly. Every blocked entry is a potential loss avoided.

The logs tell the story:

[Horus ✅] ETHUSDT confirmed — BUY_ABSORPTION (90%)  → trade executed
[Horus ] BTCUSDT blocked — SELL_PRESSURE (85%)    → entry skipped
[Horus ] SOLUSDT blocked — LIQUIDITY_EVENT (99%)  → entry skipped
[Horus ⏳] ADAUSDT waiting — NEUTRAL (60%)           → no conviction

The ratio of blocked to confirmed entries will vary by market condition. In volatile or manipulated markets, the filter becomes more selective. In clean trending conditions, more signals pass through.


Understanding the Key Signals

Signal What It Means Action
BUY_PRESSURE Institutional aggression on ask side ✅ Allow entry
BUY_ABSORPTION Whales absorbing sell pressure — strongest reversal signal ✅ Allow entry
SELL_PRESSURE Institutional selling dominant Block entry
LIQUIDITY_EVENT Flash crash setup detected Block entry
EMERGENCY_DUMP Aggressive institutional exit Block entry
SPOOFING_DETECTED Fake bid/ask walls placed to mislead Block entry
NEUTRAL No clear institutional intent ⏳ Wait

What BUY_ABSORPTION Actually Looks Like

This is the signal worth understanding in depth. During a period when BTC and SOL were both showing SELL_PRESSURE, ETH showed this:

{
  "symbol": "ETHUSDT",
  "signal": "BUY_ABSORPTION",
  "confidence": 0.80,
  "market_state": "COUNTER_TREND",
  "metrics": {
    "bid_ask_ratio": 21.32,
    "buy_sell_ratio": 0.78,
    "whale_activity": true
  }
}

bid_ask_ratio: 21.32 means there's 21x more bid liquidity than ask. Someone is systematically absorbing every sell order. RSI at this moment was in the low 40s — suggesting bearish conditions.

A bot running on indicators alone would see no reason to buy.
A bot reading the orderbook would see institutions quietly loading.


Tuning the Filter

The min_confidence parameter controls how selective the filter is:

# Conservative — only high-conviction signals pass
horus = HorusConnector(api_key=key, min_confidence=0.80)

# Balanced — good for most strategies
horus = HorusConnector(api_key=key, min_confidence=0.70)

# Permissive — catches more opportunities, more noise
horus = HorusConnector(api_key=key, min_confidence=0.60)

Start at 0.70 and adjust based on your strategy's characteristics.


Backtest Safety

One important note: confirm_trade_entry() is only called in live and dry-run modes. During backtesting, Freqtrade skips it entirely — so your backtests won't be affected, and you won't get errors from missing API calls.

This is by design. Orderflow data from the past doesn't exist in the way historical OHLCV data does. The filter is a live tool only.


Getting Started

# Install
pip install horus-flow-mcp requests

# Get free API key (500 calls/month on free tier)
# https://rapidapi.com/horustechltd/api/horus-flow-intelligence

# Clone the strategy template
git clone https://github.com/horustechltd/freqtrade-horus-strategy

# Run dry
export RAPIDAPI_KEY="your_key"
freqtrade trade --strategy HorusFlowStrategy --dry-run

Free tier: 500 API calls/month — enough for testing and low-frequency strategies.
Pro tier ($29/month): 100,000 calls — suitable for active bots across multiple pairs.


What's Next

If you want to go deeper:

  • Emergency exit protection: Use custom_exit() to close positions when LIQUIDITY_EVENT is detected mid-trade
  • US Equities: The same API works for stocks — get_equity_flow("NVDA") returns institutional orderflow for US markets
  • Multi-pair scanner: scan_crypto_flow() checks multiple symbols in one call — useful for portfolio-level decisions

The full strategy template with emergency exit logic is available at:
github.com/horustechltd/freqtrade-horus-strategy


All trade data and orderflow readings in this article come from live production systems. Past performance does not guarantee future results. This is not financial advice.


About the author:
Ashraf Hanafy is the founder of Horus Tech Ltd, building institutional-grade market microstructure intelligence for AI trading agents.

More Posts

Dashboard Operasional Armada Rental Mobil dengan Python + FastAPI

Masbadar - Mar 12

Sovereign Intelligence: The Complete 25,000 Word Blueprint (Download)

Pocket Portfolioverified - Apr 1

I’m a Senior Dev and I’ve Forgotten How to Think Without a Prompt

Karol Modelskiverified - Mar 19

I Wrote a Script to Fix Audible's Unreadable PDF Filenames

snapsynapseverified - Apr 20

How I Built a React Portfolio in 7 Days That Landed ₹1.2L in Freelance Work

Dharanidharan - Feb 9
chevron_left

Related Jobs

View all jobs →

Commenters (This Week)

2 comments
1 comment
1 comment

Contribute meaningful comments to climb the leaderboard and earn badges!