"""
OF-Trader — Configuration
=========================
Trades Order-Flow Imbalance signals from the Futures Screener.
Signals are produced by the screener (signal_log type=orderflow_imbalance);
this bot reads them locally on the screener VPS and executes the paper ticket.
Paper spec (from screener): maker entry, TP 2% / SL 0.5% / time-stop 10m, $50 × 5x.
"""
import os
# ============================================================
# BINANCE
# ============================================================
BINANCE_API_KEY = os.getenv("BINANCE_API_KEY", "")
BINANCE_API_SECRET = os.getenv("BINANCE_API_SECRET", "")
BINANCE_TESTNET = os.getenv("BINANCE_TESTNET", "true").lower() == "true"
# ============================================================
# TELEGRAM (reuse grid-bot's own bot — NOT Bender)
# ============================================================
TELEGRAM_BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN", "")
TELEGRAM_CHAT_ID = os.getenv("TELEGRAM_CHAT_ID", "")
# ============================================================
# SAFETY
# ============================================================
# DRY_RUN=true → read signals + log intended trades, place NO orders.
DRY_RUN = os.getenv("DRY_RUN", "true").lower() == "true"
# In DRY there are ~130 signals/hr — per-trade TG would spam. Off by default;
# set true for the firehose. Live trades always notify regardless.
TG_NOTIFY_DRY = os.getenv("TG_NOTIFY_DRY", "false").lower() == "true"
# ============================================================
# SIGNAL SOURCE (screener DB, read locally on the VPS)
# ============================================================
SCREENER_DB_PATH = os.getenv(
"SCREENER_DB_PATH",
"/home/app/futures-screener/server/data/users.db",
)
OF_SIGNAL_TYPE = "orderflow_imbalance"
POLL_INTERVAL_SEC = float(os.getenv("POLL_INTERVAL_SEC", "3"))
# Optional pre-trade filters on top of what the screener already emitted.
# 0 = take every signal the screener produced.
OF_MIN_CONFIDENCE = float(os.getenv("OF_MIN_CONFIDENCE", "0"))
OF_MIN_IMBALANCE = float(os.getenv("OF_MIN_IMBALANCE", "0"))
# ============================================================
# OF PAPER BRACKET (mirrors screener ticket)
# ============================================================
OF_TP_PCT = float(os.getenv("OF_TP_PCT", "2.0"))
OF_SL_PCT = float(os.getenv("OF_SL_PCT", "0.5"))
OF_HOLD_MAX_MIN = float(os.getenv("OF_HOLD_MAX_MIN", "10"))
OF_CAPITAL_USD = float(os.getenv("OF_CAPITAL_USD", "50"))
OF_LEVERAGE = int(os.getenv("OF_LEVERAGE", "5"))
# ============================================================
# MAKER ENTRY CHASE (perekos lives seconds — short total window)
# ============================================================
CHASE_MAX_SEC = float(os.getenv("CHASE_MAX_SEC", "8")) # give up after this → skip signal
CHASE_REPRICE_SEC = float(os.getenv("CHASE_REPRICE_SEC", "2")) # wait this long per price before re-pricing
CHASE_POLL_SEC = float(os.getenv("CHASE_POLL_SEC", "0.3")) # fill-status poll cadence
# ============================================================
# RISK MANAGEMENT
# ============================================================
MAX_CONCURRENT_POSITIONS = int(os.getenv("MAX_CONCURRENT_POSITIONS", "1"))
MAX_NOTIONAL_USD = float(os.getenv("MAX_NOTIONAL_USD", "250")) # OF_CAPITAL × leverage = $250
DAILY_LOSS_LIMIT_USD = float(os.getenv("DAILY_LOSS_LIMIT_USD", "10"))
KILL_SWITCH_FILE = os.path.join(
os.path.dirname(os.path.dirname(__file__)), "data", "KILL"
)
# ============================================================
# COMMISSION
# ============================================================
MAKER_FEE = 0.0002
TAKER_FEE = 0.0004
# ============================================================
# TMM
# ============================================================
TMM_STRATEGY_TAG = os.getenv("TMM_STRATEGY_TAG", "OF.v1")
TMM_TAG_COL_STRATEGY = int(os.getenv("TMM_TAG_COL_STRATEGY", "10"))
TMM_TAG_COL_ENTRY = 1
# ============================================================
# FILES
# ============================================================
DATA_DIR = os.path.join(os.path.dirname(os.path.dirname(__file__)), "data")
LAST_SEEN_FILE = os.path.join(DATA_DIR, "last_seen_signal.json")
TRADE_LOG_FILE = os.path.join(DATA_DIR, "trade_log.json")
📜 Git History
c0e676dfeat(of-trader): trade journal + notification policy (chunk 3b)4 weeks ago
c2258e0feat(of-trader): maker chase + bracket + time-stop lifecycle (chunk 2b)4 weeks ago
4480f03feat(of-trader): signal reader + dry-run loop4 weeks ago
120af73chore: archive grid-v3, scaffold of-trader from grid infra4 weeks ago
Show last diff
Loading...