Skip to content
Get a free API key — 7-day trial, no card

/docs/guard

ERS Guard

Add an entry-risk check to your bot in 3 lines. Works with a free 7-day trial key.

What it is, and what it is not

ERS Guard is a small open-source client (MIT) that asks the Entry Risk Score API one question before your bot opens a position: how risky is it to enter this symbol and side now, compared with that coin's own history? It returns a level your own rules can use.

It is not a strategy and not advice: it computes nothing, leaves your bot's logic unchanged and never decides for you. Python 3.9+ without dependencies, a single-file JavaScript client and a local sidecar for any language. Source: github.com/entryriskscore/ers-guard · release v0.1.1. Tested on Linux, Windows and macOS with Python 3.9–3.13.

Install

pip install git+https://github.com/entryriskscore/ers-guard
export ERS_API_KEY=ers_your_key        # dashboard → API & MCP; a free 7-day trial key works (10 coins)

Quickstart (3 lines)

from ers_guard import Guard
guard = Guard()
print(guard.check("ETHUSDT", "LONG", hold="60m"))
r = guard.check("ETHUSDT", "LONG", hold="60m")    # hold: 60m | 8h | 24h
r.level, r.score, r.as_of, r.reason

if guard.allow_entry("ETHUSDT", "LONG", block={"HIGH"}):   # your policy
    place_order(...)
levelMeaning
HIGHRisk Score 80/100 or above
ELEVATED60–79
NORMALbelow 60 (not HIGH does not mean low risk)
UNKNOWNno current answer: data older than 12 min, API unreachable, key problem
NOT_COVEREDnot in your key's plan, or not a USDT-M perpetual

Policies

allow_entry(symbol, side, hold="60m", block={"HIGH"}) blocks any set of levels. Guard(on_unknown="allow") (default) or "block" decides what UNKNOWN and NOT_COVERED mean for your bot. Guard never presents stale data as current.

Quota behaviour

One GET /api/v1/state per 5-minute update cycle, cached until meta.next_update_at; never more than one request per 60 seconds, whatever your code does; Retry-After respected. A trial key needs at most 288 requests a day (quota 500).

Command line

ers-guard check ETHUSDT LONG --hold 8h --json
ers-guard check ETHUSDT LONG --fail-on HIGH && ./my_entry.sh   # exit 0 ok, 2 matched, 3 UNKNOWN/NOT_COVERED
ers-guard status

Sidecar for any language

ers-guard serve --port 8787 --file ers_state.json
curl "http://127.0.0.1:8787/check?symbol=ETHUSDT&side=LONG&hold=60m"

Listens on 127.0.0.1 only; /check, /state, /health. On Windows, read the state file and close it at once, or use the HTTP endpoint.

Integrations

Freqtrade

from ers_guard_mixin import ErsGuardMixin

class MyStrategy(ErsGuardMixin, IStrategy):
    ers_block = {"HIGH"}     # checked in confirm_trade_entry; exits are never blocked
    ers_hold = "60m"

Hummingbot

from ers_guard import Guard
GUARD = Guard()
if GUARD.allow_entry("ETH-USDT", "LONG", block=("HIGH",)):
    ...   # your order

ccxt

from guarded import guarded_create_order, EntryBlocked
order = guarded_create_order(exchange, "ETH/USDT:USDT", "limit", "buy", 0.1, 2500)   # reduceOnly orders pass through

JavaScript (Node 18+)

const { ErsGuard } = require('./js/ers-guard.js');
const guard = new ErsGuard();          // ERS_API_KEY from the environment
if (await guard.allowEntry('ETH/USDT:USDT', 'LONG', { block: ['HIGH'] })) { /* your order */ }

Go and C# snippets that read the sidecar are in the repository's examples/ folder.

DATA NOTICEEntry Risk Score is a data service that measures entry-timing risk on Binance USDT-M futures. It is not a signal, not investment advice, and makes no promise of returns. Published rates describe the past and do not guarantee future results. You are solely responsible for your trading decisions.