[Add] Add oms engine
This commit is contained in:
parent
6ceac176ac
commit
a899060360
@ -4,7 +4,9 @@ from vnpy.trader.ui import MainWindow, create_qapp
|
|||||||
|
|
||||||
from vnpy.trader.ui.widget import TickMonitor
|
from vnpy.trader.ui.widget import TickMonitor
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
|
def main():
|
||||||
|
""""""
|
||||||
qapp = create_qapp()
|
qapp = create_qapp()
|
||||||
|
|
||||||
event_engine = EventEngine()
|
event_engine = EventEngine()
|
||||||
@ -16,4 +18,8 @@ if __name__ == "__main__":
|
|||||||
monitor = TickMonitor(main_engine, event_engine)
|
monitor = TickMonitor(main_engine, event_engine)
|
||||||
monitor.show()
|
monitor.show()
|
||||||
|
|
||||||
qapp.exec()
|
qapp.exec()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
@ -8,9 +8,10 @@ from vnpy.event import EventEngine, Event
|
|||||||
|
|
||||||
from .event import EVENT_LOG
|
from .event import EVENT_LOG
|
||||||
from .object import LogData, SubscribeRequest, OrderRequest, CancelRequest
|
from .object import LogData, SubscribeRequest, OrderRequest, CancelRequest
|
||||||
from .utility import Singleton, get_temp_path
|
from .utility import Singleton, get_temp_path, check_order_active
|
||||||
from .setting import SETTINGS
|
from .setting import SETTINGS
|
||||||
|
|
||||||
|
|
||||||
class MainEngine:
|
class MainEngine:
|
||||||
"""
|
"""
|
||||||
Acts as the core of VN Trader.
|
Acts as the core of VN Trader.
|
||||||
@ -25,10 +26,34 @@ class MainEngine:
|
|||||||
self.event_engine.start()
|
self.event_engine.start()
|
||||||
|
|
||||||
self.gateways = {}
|
self.gateways = {}
|
||||||
|
self.engines = {}
|
||||||
self.apps = {}
|
self.apps = {}
|
||||||
|
|
||||||
self.log_engine = LogEngine(self, self.event_engine)
|
self.init_engines()
|
||||||
|
|
||||||
|
def init_engines:
|
||||||
|
"""
|
||||||
|
Init all engines.
|
||||||
|
"""
|
||||||
|
# Log Engine
|
||||||
|
self.engines["log"] = LogEngine(self, self.event_engine)
|
||||||
|
|
||||||
|
# OMS Engine
|
||||||
|
self.engines["oms"] = OmsEngine(self, self.event_engine)
|
||||||
|
|
||||||
|
oms_engine = self.engines["oms"]
|
||||||
|
self.get_tick = oms_engine.get_tick
|
||||||
|
self.get_order = oms_engine.get_order
|
||||||
|
self.get_position = oms_engine.get_position
|
||||||
|
self.get_account = oms_engine.get_account
|
||||||
|
self.get_contract = oms_engine.get_contract
|
||||||
|
self.get_all_ticks = oms.get_all_ticks
|
||||||
|
self.get_all_orders = oms.get_all_orders
|
||||||
|
self.get_all_trades = oms.get_all_trades
|
||||||
|
self.get_all_positions = oms.get_all_positions
|
||||||
|
self.get_all_accounts = oms.get_all_accounts
|
||||||
|
self.get_all_active_orders = oms.get_all_active_orders
|
||||||
|
|
||||||
def write_log(self, msg: str):
|
def write_log(self, msg: str):
|
||||||
"""
|
"""
|
||||||
Put log event with specific message.
|
Put log event with specific message.
|
||||||
@ -91,7 +116,7 @@ class MainEngine:
|
|||||||
|
|
||||||
class LogEngine:
|
class LogEngine:
|
||||||
"""
|
"""
|
||||||
Process log event and output with logging module.
|
Processes log event and output with logging module.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__metaclass__ = Singleton
|
__metaclass__ = Singleton
|
||||||
@ -106,13 +131,15 @@ class LogEngine:
|
|||||||
|
|
||||||
self.level = SETTINGS["log.level"]
|
self.level = SETTINGS["log.level"]
|
||||||
self.logger = logging.getLogger("VN Trader")
|
self.logger = logging.getLogger("VN Trader")
|
||||||
self.formatter = logging.Formatter("%(asctime)s %(levelname)s: %(message)s")
|
self.formatter = logging.Formatter(
|
||||||
|
"%(asctime)s %(levelname)s: %(message)s"
|
||||||
|
)
|
||||||
|
|
||||||
self.add_null_handler()
|
self.add_null_handler()
|
||||||
|
|
||||||
if SETTINGS["log.console"]:
|
if SETTINGS["log.console"]:
|
||||||
self.add_console_handler()
|
self.add_console_handler()
|
||||||
|
|
||||||
if SETTINGS["log.file"]:
|
if SETTINGS["log.file"]:
|
||||||
self.add_file_handler()
|
self.add_file_handler()
|
||||||
|
|
||||||
@ -124,7 +151,7 @@ class LogEngine:
|
|||||||
"""
|
"""
|
||||||
null_handler = logging.NullHandler()
|
null_handler = logging.NullHandler()
|
||||||
self.logger.addHandler(null_handler)
|
self.logger.addHandler(null_handler)
|
||||||
|
|
||||||
def add_console_handler(self):
|
def add_console_handler(self):
|
||||||
"""
|
"""
|
||||||
Add console output of log.
|
Add console output of log.
|
||||||
@ -133,7 +160,7 @@ class LogEngine:
|
|||||||
console_handler.setLevel(self.level)
|
console_handler.setLevel(self.level)
|
||||||
console_handler.setFormatter(self.formatter)
|
console_handler.setFormatter(self.formatter)
|
||||||
self.logger.addHandler(console_handler)
|
self.logger.addHandler(console_handler)
|
||||||
|
|
||||||
def add_file_handler(self):
|
def add_file_handler(self):
|
||||||
"""
|
"""
|
||||||
Add file output of log.
|
Add file output of log.
|
||||||
@ -152,6 +179,160 @@ class LogEngine:
|
|||||||
self.event_engine.register(EVENT_LOG, self.process_log_event)
|
self.event_engine.register(EVENT_LOG, self.process_log_event)
|
||||||
|
|
||||||
def process_log_event(self, event: Event):
|
def process_log_event(self, event: Event):
|
||||||
""""""
|
"""
|
||||||
|
Output log event data with logging function.
|
||||||
|
"""
|
||||||
log = event.data
|
log = event.data
|
||||||
self.logger.log(log.level, log.msg)
|
self.logger.log(log.level, log.msg)
|
||||||
|
|
||||||
|
|
||||||
|
class OmsEngine:
|
||||||
|
"""
|
||||||
|
Provides order management system function for VN Trader.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, main_engine: MainEngine, event_engine: EventEngine):
|
||||||
|
""""""
|
||||||
|
self.main_engine = main_engine
|
||||||
|
self.event_engine = event_engine
|
||||||
|
|
||||||
|
self.ticks = {}
|
||||||
|
self.orders = {}
|
||||||
|
self.trades = {}
|
||||||
|
self.positions = {}
|
||||||
|
self.accounts = {}
|
||||||
|
self.contracts = {}
|
||||||
|
|
||||||
|
self.active_orders = {}
|
||||||
|
|
||||||
|
self.register_event()
|
||||||
|
|
||||||
|
def register_event(self):
|
||||||
|
""""""
|
||||||
|
self.event_engine.register(EVENT_TICK, self.process_tick_event)
|
||||||
|
self.event_engine.register(EVENT_ORDER, self.process_order_event)
|
||||||
|
self.event_engine.register(EVENT_TRADE, self.process_trade_event)
|
||||||
|
self.event_engine.register(EVENT_POSITION, self.process_position_event)
|
||||||
|
self.event_engine.register(EVENT_ACCOUNT, self.process_account_event)
|
||||||
|
self.event_engine.register(EVENT_CONTRACT, self.process_contract_event)
|
||||||
|
|
||||||
|
def process_tick_event(self, event: Event):
|
||||||
|
""""""
|
||||||
|
tick = event.data
|
||||||
|
self.ticks[tick.vt_symbol] = tick
|
||||||
|
|
||||||
|
def process_order_event(self, event: Event):
|
||||||
|
""""""
|
||||||
|
order = event.data
|
||||||
|
self.orders[order.vt_orderid] = order
|
||||||
|
|
||||||
|
# If order is active, then update data in dict.
|
||||||
|
if check_order_active(order.status):
|
||||||
|
self.active_orders[order.vt_orderid] = order
|
||||||
|
# Otherwise, pop inactive order from in dict
|
||||||
|
elif order.vt_orderid in self.active_orders:
|
||||||
|
self.active_orders.pop(order.vt_orderid)
|
||||||
|
|
||||||
|
def process_trade_event(self, event: Event):
|
||||||
|
""""""
|
||||||
|
trade = event.data
|
||||||
|
self.trades[trade.vt_tradeid] = trade
|
||||||
|
|
||||||
|
def process_position_event(self, event: Event):
|
||||||
|
""""""
|
||||||
|
position = event.data
|
||||||
|
self.positions[position.vt_positionid] = position
|
||||||
|
|
||||||
|
def process_account_event(self, event: Event):
|
||||||
|
""""""
|
||||||
|
account = event.data
|
||||||
|
self.accounts[account.vt_accountid] = account
|
||||||
|
|
||||||
|
def process_contract_event(self, event: Event):
|
||||||
|
""""""
|
||||||
|
contract = event.data
|
||||||
|
self.contracts[contract.vt_symbol]] = contract
|
||||||
|
|
||||||
|
def get_tick(self, vt_symbol):
|
||||||
|
"""
|
||||||
|
Get latest market tick data by vt_symbol.
|
||||||
|
"""
|
||||||
|
return self.ticks.get(vt_symbol, None)
|
||||||
|
|
||||||
|
def get_order(self, vt_orderid):
|
||||||
|
"""
|
||||||
|
Get latest order data by vt_orderid.
|
||||||
|
"""
|
||||||
|
return self.orders.get(vt_orderid, None)
|
||||||
|
|
||||||
|
def get_trade(self, vt_tradeid):
|
||||||
|
"""
|
||||||
|
Get trade data by vt_tradeid.
|
||||||
|
"""
|
||||||
|
return self.trades.get(vt_tradeid, None)
|
||||||
|
|
||||||
|
def get_position(self, vt_positionid):
|
||||||
|
"""
|
||||||
|
Get latest position data by vt_positionid.
|
||||||
|
"""
|
||||||
|
return self.positions.get(vt_positionid, None)
|
||||||
|
|
||||||
|
def get_account(self, vt_accountid):
|
||||||
|
"""
|
||||||
|
Get latest account data by vt_accountid.
|
||||||
|
"""
|
||||||
|
return self.accounts.get(vt_accountid, None)
|
||||||
|
|
||||||
|
def get_contract(self, vt_symbol):
|
||||||
|
"""
|
||||||
|
Get contract data by vt_symbol.
|
||||||
|
"""
|
||||||
|
return self.contracts.get(vt_symbol, None)
|
||||||
|
|
||||||
|
def get_all_ticks(self):
|
||||||
|
"""
|
||||||
|
Get all tick data.
|
||||||
|
"""
|
||||||
|
return list(self.ticks.values())
|
||||||
|
|
||||||
|
def get_all_orders(self):
|
||||||
|
"""
|
||||||
|
Get all order data.
|
||||||
|
"""
|
||||||
|
return list(self.orders.values())
|
||||||
|
|
||||||
|
def get_all_trades(self):
|
||||||
|
"""
|
||||||
|
Get all trade data.
|
||||||
|
"""
|
||||||
|
return list(self.trades.values())
|
||||||
|
|
||||||
|
def get_all_positions(self):
|
||||||
|
"""
|
||||||
|
Get all position data.
|
||||||
|
"""
|
||||||
|
return list(self.positions.values())
|
||||||
|
|
||||||
|
def get_all_accounts(self):
|
||||||
|
"""
|
||||||
|
Get all account data.
|
||||||
|
"""
|
||||||
|
return list(self.accounts.values())
|
||||||
|
|
||||||
|
def get_all_contracts(self):
|
||||||
|
"""
|
||||||
|
Get all contract data.
|
||||||
|
"""
|
||||||
|
return list(self.contracts.values())
|
||||||
|
|
||||||
|
def get_all_active_orders(self, vt_symbol: str=''):
|
||||||
|
"""
|
||||||
|
Get all active orders by vt_symbol.
|
||||||
|
|
||||||
|
If vt_symbol is empty, return all active orders.
|
||||||
|
"""
|
||||||
|
if not vt_symbol:
|
||||||
|
return list(self.active_orders.values())
|
||||||
|
else:
|
||||||
|
active_orders = [order for order in self.active_orders.values() if order.vt_symbol == vt_symbol]
|
||||||
|
return active_orders
|
@ -4,6 +4,9 @@ General utility functions.
|
|||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
from .constant import (STATUS_NOTTRADED, STATUS_PARTTRADED, STATUS_SUBMITTING)
|
||||||
|
|
||||||
|
|
||||||
class Singleton(type):
|
class Singleton(type):
|
||||||
"""
|
"""
|
||||||
Singleton metaclass,
|
Singleton metaclass,
|
||||||
@ -17,12 +20,14 @@ class Singleton(type):
|
|||||||
def __call__(cls, *args, **kwargs):
|
def __call__(cls, *args, **kwargs):
|
||||||
""""""
|
""""""
|
||||||
if cls not in cls._instances:
|
if cls not in cls._instances:
|
||||||
cls._instances[cls] = super(VtSingleton, cls).__call__(*args, **kwargs)
|
cls._instances[cls] = super(VtSingleton,
|
||||||
|
cls).__call__(*args,
|
||||||
|
**kwargs)
|
||||||
|
|
||||||
return cls._instances[cls]
|
return cls._instances[cls]
|
||||||
|
|
||||||
|
|
||||||
def get_temp_path(filename):
|
def get_temp_path(filename: str):
|
||||||
"""
|
"""
|
||||||
Get path for temp file with filename.
|
Get path for temp file with filename.
|
||||||
"""
|
"""
|
||||||
@ -31,5 +36,18 @@ def get_temp_path(filename):
|
|||||||
|
|
||||||
if not temp_path.exists():
|
if not temp_path.exists():
|
||||||
temp_path.mkdir()
|
temp_path.mkdir()
|
||||||
|
|
||||||
return temp_path.joinpath(filename)
|
return temp_path.joinpath(filename)
|
||||||
|
|
||||||
|
|
||||||
|
ACTIVE_STATUSES = set([STATUS_SUBMITTING, STATUS_NOTTRADED, STATUS_PARTTRADED])
|
||||||
|
|
||||||
|
|
||||||
|
def check_order_active(status: str):
|
||||||
|
"""
|
||||||
|
Check if order is active by status.
|
||||||
|
"""
|
||||||
|
if status in ACTIVE_STATUSES:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
Loading…
Reference in New Issue
Block a user