Trading Rules¶
The rules module enforces exchange constraints on trading operations. Every trading pair on every exchange has a set of rules that determine what orders are valid.
TradingRule¶
TradingRule is a Pydantic model that captures the constraints for a single trading pair.
from decimal import Decimal
from financepype.markets.trading_pair import TradingPair
from financepype.rules.trading_rule import TradingRule
from financepype.operations.orders.models import OrderType, OrderModifier
rule = TradingRule(
trading_pair=TradingPair(name="BTC-USDT"),
min_order_size=Decimal("0.001"),
max_order_size=Decimal("100"),
min_price_increment=Decimal("0.01"),
min_base_amount_increment=Decimal("0.00001"),
min_quote_amount_increment=Decimal("0.01"),
min_notional_size=Decimal("10"),
max_notional_size=Decimal("1000000"),
supported_order_types={OrderType.LIMIT, OrderType.MARKET},
supported_order_modifiers={OrderModifier.POST_ONLY, OrderModifier.REDUCE_ONLY},
is_live=True,
)
Fields¶
| Field | Default | Description |
|---|---|---|
trading_pair |
required | The pair these rules apply to |
min_order_size |
0 |
Minimum size in base currency |
max_order_size |
1e20 |
Maximum size in base currency |
min_price_increment |
1e-20 |
Tick size (price step) |
min_price_significance |
0 |
Minimum significant price digits |
min_base_amount_increment |
1e-20 |
Size step for base currency |
min_quote_amount_increment |
1e-20 |
Size step for quote currency |
min_notional_size |
0 |
Minimum order value in quote |
max_notional_size |
1e20 |
Maximum order value in quote |
supported_order_types |
{LIMIT, MARKET} |
Allowed order types |
supported_order_modifiers |
{POST_ONLY} |
Allowed order modifiers |
buy_order_collateral_token |
quote currency |
Collateral for buy orders |
sell_order_collateral_token |
base currency |
Collateral for sell orders |
product_id |
None |
Exchange-specific product ID |
is_live |
True |
Whether trading is enabled |
other_rules |
{} |
Extra exchange-specific constraints |
Properties¶
rule.supports_limit_orders # True if LIMIT in supported_order_types
rule.supports_market_orders # True if MARKET in supported_order_types
rule.active # is_active() with no timestamp
rule.started # is_started() with no timestamp
rule.expired # is_expired() with no timestamp
Lifecycle Methods¶
For spot rules, these always return the same static values:
rule.is_active() # True (always active for spot)
rule.is_started() # True (always started for spot)
rule.is_expired() # False (never expires for spot)
Pass a timestamp to check at a specific point in time (used mainly for derivatives):
rule.is_active(timestamp=1700000000)
Collateral Token Defaults¶
If buy_order_collateral_token or sell_order_collateral_token are not specified, they are set automatically:
- Buy orders: collateral = quote currency
- Sell orders: collateral = base currency
rule = TradingRule(trading_pair=TradingPair(name="BTC-USDT"))
print(rule.buy_order_collateral_token) # USDT
print(rule.sell_order_collateral_token) # BTC
DerivativeTradingRule¶
DerivativeTradingRule extends TradingRule with derivative-specific attributes.
from financepype.rules.trading_rule import DerivativeTradingRule
# Perpetual contract (expiry_timestamp = -1)
perp_rule = DerivativeTradingRule(
trading_pair=TradingPair(name="BTC-USDT-PERPETUAL"),
expiry_timestamp=-1,
underlying="BTC",
index_symbol="BTC/USD",
)
print(perp_rule.perpetual) # True
print(perp_rule.is_expired()) # False
# Expiring future
future_rule = DerivativeTradingRule(
trading_pair=TradingPair(name="BTC-USDT-FUTURE-1W-20260101"),
expiry_timestamp=1767225600.0, # 2026-01-01 00:00 UTC
start_timestamp=1764547200.0,
underlying="BTC",
)
print(future_rule.perpetual) # False
print(future_rule.is_active()) # depends on current time
print(future_rule.is_expired(1800000000)) # True (past expiry)
Additional Fields¶
| Field | Default | Description |
|---|---|---|
underlying |
None |
Underlying asset symbol |
strike_price |
None |
Strike price for options |
start_timestamp |
0 |
When trading begins |
expiry_timestamp |
-1 |
When trading ends (−1 = perpetual) |
index_symbol |
None |
Index being tracked |
Collateral for Derivatives¶
Collateral is automatically set based on linear/inverse classification:
- Linear (PERPETUAL, FUTURE): collateral = quote for both sides
- Inverse (INVERSE_PERPETUAL, INVERSE_FUTURE): collateral = base for both sides
TradingRulesTracker¶
TradingRulesTracker is an abstract class that manages a live set of rules for an exchange. It maintains a bidirectional mapping between exchange-native symbols and standardized TradingPair names.
from financepype.rules.trading_rules_tracker import TradingRulesTracker
from bidict import bidict
class BinanceRulesTracker(TradingRulesTracker):
async def update_trading_rules(self) -> None:
# Fetch from exchange API
raw_rules = await self.exchange.get_exchange_info()
rules = {}
symbol_map = bidict()
for item in raw_rules["symbols"]:
pair = TradingPair(name=f"{item['baseAsset']}-{item['quoteAsset']}")
rule = TradingRule(
trading_pair=pair,
min_order_size=Decimal(item["minQty"]),
min_price_increment=Decimal(item["tickSize"]),
)
rules[pair] = rule
symbol_map[pair] = item["symbol"]
self.set_trading_rules(rules)
self.set_trading_pair_symbol_map(symbol_map)
Usage¶
tracker = BinanceRulesTracker()
await tracker.update_trading_rules()
# Check readiness
print(tracker.is_ready) # True after first successful update
print(tracker.is_locked) # True while updating
# Query
all_pairs = await tracker.all_trading_pairs()
exchange_sym = await tracker.exchange_symbol_associated_to_pair(
TradingPair(name="BTC-USDT")
) # e.g. "BTCUSDT"
std_pair = await tracker.trading_pair_associated_to_exchange_symbol("BTCUSDT")
# Validation
valid = await tracker.is_trading_pair_valid(TradingPair(name="BTC-USDT"))
Background Update Loop¶
import asyncio
async def main():
tracker = BinanceRulesTracker()
# Update every 30 minutes
task = asyncio.create_task(tracker.update_loop(interval_seconds=1800))
...
asyncio.run(main())
Direct Rule Access¶
rules = tracker.trading_rules # dict[TradingPair, TradingRule]
btc_rule = rules.get(TradingPair(name="BTC-USDT"))
# Update individual rule
tracker.set_trading_rule(TradingPair(name="ETH-USDT"), new_rule)
# Remove a rule
tracker.remove_trading_rule(TradingPair(name="DOGE-USDT"))