Files
QuantumTerminal/backend/models.py
T

178 lines
3.9 KiB
Python

"""
models.py — Data models for consumer terminal.
Provides TickData, BarData, etc. that providers and data_server import.
All classes accept and silently ignore unknown keyword arguments
so PRO provider code that passes extra fields won't crash.
"""
from typing import Optional, Dict, Any
from datetime import datetime
def _make_flex(cls):
"""Decorator: wraps __init__ to silently drop unknown kwargs."""
orig = cls.__init__
import inspect
params = set(inspect.signature(orig).parameters.keys()) - {'self'}
def flex_init(self, *args, **kwargs):
valid = {k: v for k, v in kwargs.items() if k in params}
orig(self, *args, **valid)
# Store extras as attributes
for k, v in kwargs.items():
if k not in params:
setattr(self, k, v)
cls.__init__ = flex_init
# Add to_dict if not present
if not hasattr(cls, 'to_dict'):
def to_dict(self):
d = {}
for k in params:
d[k] = getattr(self, k, None)
for k, v in self.__dict__.items():
if k not in d:
d[k] = v
return d
cls.to_dict = to_dict
return cls
from dataclasses import dataclass
@_make_flex
@dataclass
class TickData:
ticker: str = ""
symbol: str = ""
bid: float = 0.0
ask: float = 0.0
last: float = 0.0
volume: float = 0.0
time: Optional[datetime] = None
spread: float = 0.0
time_msc: int = 0
flags: int = 0
volume_real: float = 0.0
@_make_flex
@dataclass
class BarData:
ticker: str = ""
symbol: str = ""
timeframe: str = ""
time: Optional[datetime] = None
open: float = 0.0
high: float = 0.0
low: float = 0.0
close: float = 0.0
volume: float = 0.0
tick_volume: float = 0.0
spread: int = 0
real_volume: float = 0.0
@_make_flex
@dataclass
class AccountInfo:
balance: float = 0.0
equity: float = 0.0
margin: float = 0.0
free_margin: float = 0.0
currency: str = "USD"
leverage: int = 100
server: str = ""
login: int = 0
name: str = ""
company: str = ""
profit: float = 0.0
margin_level: float = 0.0
@_make_flex
@dataclass
class SymbolInfo:
ticker: str = ""
symbol: str = ""
description: str = ""
point: float = 0.0
digits: int = 5
tick_size: float = 0.0
tick_value: float = 0.0
volume_min: float = 0.01
volume_max: float = 100.0
volume_step: float = 0.01
trade_contract_size: float = 100000.0
currency_base: str = ""
currency_profit: str = ""
currency_margin: str = ""
spread: int = 0
trade_mode: int = 0
trade_stops_level: int = 0
swap_long: float = 0.0
swap_short: float = 0.0
@_make_flex
@dataclass
class OrderRequest:
symbol: str = ""
ticker: str = ""
direction: str = ""
volume: float = 0.01
price: float = 0.0
sl: float = 0.0
tp: float = 0.0
comment: str = ""
order_type: str = "market"
@_make_flex
@dataclass
class OrderResult:
success: bool = False
order_id: int = 0
message: str = ""
price: float = 0.0
volume: float = 0.0
retcode: int = 0
@_make_flex
@dataclass
class Position:
ticket: int = 0
symbol: str = ""
ticker: str = ""
direction: str = ""
volume: float = 0.0
price_open: float = 0.0
price_current: float = 0.0
sl: float = 0.0
tp: float = 0.0
profit: float = 0.0
comment: str = ""
time_open: Optional[datetime] = None
swap: float = 0.0
commission: float = 0.0
@_make_flex
@dataclass
class PendingOrder:
"""A resting (unfilled) order — LIMIT or STOP — on the broker."""
ticket: int = 0
symbol: str = ""
ticker: str = ""
direction: str = "" # "BUY" | "SELL"
order_type: str = "" # "LIMIT" | "STOP"
volume: float = 0.0
price_open: float = 0.0
sl: float = 0.0
tp: float = 0.0
comment: str = ""
time_setup: Optional[datetime] = None