Core Concepts¶
Understanding these core concepts will help you use qlcore effectively.
Design Philosophy¶
Pure Computation¶
qlcore is a pure computation library. It has:
- ✅ Mathematical functions and domain models
- ✅ Type definitions and validation
- ❌ No network I/O
- ❌ No database connections
- ❌ No file system operations (except explicit save/load)
- ❌ No external API calls
This makes qlcore:
- Testable — Deterministic, no mocks needed
- Portable — Works anywhere Python runs
- Composable — Integrate with any data source or execution layer
Decimal Precision¶
All financial calculations use Python's Decimal type:
from decimal import Decimal
# qlcore accepts multiple input types
qc.Fill.create(
quantity="0.1", # String → Decimal internally
price=Decimal("45000"), # Decimal directly
fee=4.5, # Float → converted to Decimal
...
)
Avoid Float Arithmetic
Immutability¶
Positions are immutable frozen dataclasses:
position = qc.SpotPosition(
instrument_id="BTC-USD",
side=qc.PositionSide.LONG,
size=Decimal("1.0"),
avg_entry_price=Decimal("45000"),
)
# Positions cannot be modified
position.size = Decimal("2.0") # ❌ Raises error
# Instead, create a new position with evolve()
new_position = position.evolve(size=Decimal("2.0")) # ✅
This design provides:
- Thread safety — Share positions across threads
- Audit trail — Every state is a separate snapshot
- Debugging — Compare any two states easily
Position Types¶
qlcore supports three position types for different instruments:
SpotPosition¶
For spot markets and equities where you own the underlying asset.
position = qc.SpotPosition(
instrument_id="BTC-USD",
side=qc.PositionSide.LONG,
size=Decimal("1.0"),
avg_entry_price=Decimal("45000"),
)
Key characteristics:
- No leverage
- No funding payments
- No expiration
PerpetualPosition¶
For perpetual futures contracts that never expire.
position = qc.PerpetualPosition(
instrument_id="BTC-USDT-PERP",
side=qc.PositionSide.LONG,
size=Decimal("1.0"),
avg_entry_price=Decimal("45000"),
accumulated_funding=Decimal("-12.50"), # Funding paid
)
Key characteristics:
- Leveraged (margin required)
- Funding payments every 8 hours (typically)
- Tracks accumulated funding
FuturesPosition¶
For traditional futures with an expiration date.
position = qc.FuturesPosition(
instrument_id="BTC-USD-MAR25",
side=qc.PositionSide.SHORT,
size=Decimal("0.5"),
avg_entry_price=Decimal("46000"),
expiry_ms=1711929600000, # March 2025
)
Key characteristics:
- Leveraged
- Fixed expiration date
- Settlement at expiry
Domain Events¶
Events represent things that happen to positions:
Fill¶
A trade execution:
fill = qc.Fill.create(
order_id="order-001",
instrument_id="BTC-USDT-PERP",
side=qc.OrderSide.BUY,
quantity="0.1",
price="45000",
fee="4.5",
timestamp_ms=1701849600000,
)
FundingEvent¶
A funding payment on a perpetual:
funding = qc.FundingEvent(
instrument_id="BTC-USDT-PERP",
funding_rate=Decimal("0.0001"), # 0.01%
timestamp_ms=1701878400000,
)
LiquidationEvent¶
A forced position closure:
liquidation = qc.LiquidationEvent(
instrument_id="BTC-USDT-PERP",
quantity=Decimal("0.1"),
price=Decimal("40000"),
timestamp_ms=1701900000000,
)
SettlementEvent¶
A futures contract settling at expiry:
settlement = qc.SettlementEvent(
instrument_id="BTC-USD-MAR25",
settlement_price=Decimal("47000"),
timestamp_ms=1711929600000,
)
Portfolio & Account¶
Account¶
Holds cash balances across currencies:
account = qc.Account(
base_currency="USDT",
balances={
"USDT": Decimal("10000"),
"BTC": Decimal("0.5"),
},
)
Portfolio¶
Contains an account and positions:
portfolio = qc.Portfolio(account=account)
# Apply fills to update positions
portfolio = portfolio.apply_fill(fill)
# Access positions
btc_position = portfolio.positions.get("BTC-USDT-PERP")
Relationship¶
Portfolio
├── Account (balances)
└── Positions (dict)
├── "BTC-USDT-PERP" → PerpetualPosition
├── "ETH-USDT-PERP" → PerpetualPosition
└── "BTC-USD" → SpotPosition
Type System¶
qlcore uses type aliases for clarity:
| Type | Meaning | Base Type |
|---|---|---|
Money |
Currency amounts | Decimal |
Price |
Asset prices | Decimal |
Quantity |
Position sizes | Decimal |
Rate |
Percentages/rates | Decimal |
TimestampMs |
Unix milliseconds | int |
from qlcore import Money, Price, Quantity, Rate, TimestampMs
price: Price = Decimal("45000")
size: Quantity = Decimal("0.1")
fee: Money = Decimal("4.5")
rate: Rate = Decimal("0.001")
ts: TimestampMs = 1701849600000
Error Handling¶
qlcore raises specific exceptions:
| Exception | When |
|---|---|
ValidationError |
Invalid input (negative price, empty ID) |
InvalidFillError |
Malformed fill data |
MathError |
Impossible calculation |
InsufficientMargin |
Not enough margin for trade |
PositionNotFound |
Position doesn't exist |
InstrumentNotFound |
Unknown instrument |
try:
fill = qc.Fill.create(
quantity="-1", # ❌ Negative quantity
...
)
except qc.ValidationError as e:
print(f"Validation failed: {e}")
Next Steps¶
- Positions Guide — Working with positions in depth
- Portfolio Guide — Portfolio management patterns
- API Reference — Complete API documentation