回到OptionMaster

根据我们对APP调用的代码阅读,我们基本上知道了一个APP是如何被调用,那么我们回到OptionMaster学习下这个APP的实现。

看看结构

class OptionManager(QtWidgets.QWidget):
""""""
signal_new_portfolio = QtCore.pyqtSignal(Event) def __init__(self, main_engine: MainEngine, event_engine: EventEngine):
pass def init_ui(self):
pass def register_event(self):
pass def process_new_portfolio_event(self, event: Event):
pass def update_portfolio_combo(self):
pass def open_portfolio_dialog(self):
pass def init_widgets(self):
pass def calculate_underlying_adjustment(self):
pass

通过结构和注释,我们基本上知道这是一个期权方面的APP。我们来对代码进行仔细学习

__init__

    def __init__(self, main_engine: MainEngine, event_engine: EventEngine):
""""""
super().__init__() self.main_engine = main_engine
self.event_engine = event_engine
self.option_engine = main_engine.get_engine(APP_NAME) self.portfolio_name: str = "" self.market_monitor: OptionMarketMonitor = None
self.greeks_monitor: OptionGreeksMonitor = None self.docks: List[QtWidgets.QDockWidget] = [] self.init_ui()
self.register_event()

在init中我们看到和MainWindow不一样的地方出了main_engine和event_engin还加入了一个他自己的引擎,这个引擎是在app注册时候配置在engine_class中的。然后有两个报表:market_monitor和greeks_monitor

init_ui

    def init_ui(self):
#具体实现
self.portfolio_button = QtWidgets.QPushButton("配置")
self.portfolio_button.clicked.connect(self.open_portfolio_dialog)

简单的界面配置我们通过运行程序看到实现的大概如下



我们只看到portfolio_button点击以后调用了self.open_portfolio_dialog

open_portfolio_dialog

    def open_portfolio_dialog(self):
""""""
portfolio_name = self.portfolio_combo.currentText()
if not portfolio_name:
return self.portfolio_name = portfolio_name dialog = PortfolioDialog(self.option_engine, portfolio_name)
result = dialog.exec_() if result == dialog.Accepted:
self.portfolio_combo.setEnabled(False)
self.portfolio_button.setEnabled(False) self.init_widgets()

我们看到点击配置以后,如果有选择期权产品,则弹出 PortfolioDialog对话框。根据对话框的执行结果,如果点击了接受,则下拉框和配置按钮不可用,然后执行init_widgets

init_widgets

    def init_widgets(self):
""""""
self.market_monitor = OptionMarketMonitor(self.option_engine, self.portfolio_name)
self.greeks_monitor = OptionGreeksMonitor(self.option_engine, self.portfolio_name)
self.manual_trader = OptionManualTrader(self.option_engine, self.portfolio_name) self.market_monitor.itemDoubleClicked.connect(self.manual_trader.update_symbol) self.market_button.clicked.connect(self.market_monitor.showMaximized)
self.greeks_button.clicked.connect(self.greeks_monitor.showMaximized)
self.manual_button.clicked.connect(self.manual_trader.show)
self.chain_button.clicked.connect(self.calculate_underlying_adjustment) for button in [
self.market_button,
self.greeks_button,
self.chain_button,
self.manual_button
]:
button.setEnabled(True)

我们看到则是对market_monitor,greeks_monitor,manual_trader进行实例化,并且绑定了事件的信号插槽。同时对一些按钮进行了绑定,基本上都是窗体的显示。主要是以下按钮和窗体的显示的对应

        self.market_button = QtWidgets.QPushButton("T型报价")
self.greeks_button = QtWidgets.QPushButton("持仓希腊值")
self.chain_button = QtWidgets.QPushButton("拟合升贴水")
self.manual_button = QtWidgets.QPushButton("快速交易")

而且每一个窗体都传入了该APP定义的engine

register_event

我们在__init__方法中同时看到了此方法的调用。

    def register_event(self):
""""""
self.signal_new_portfolio.connect(self.process_new_portfolio_event) self.event_engine.register(EVENT_OPTION_NEW_PORTFOLIO, self.signal_new_portfolio.emit)

我们看到该方法把 process_new_portfolio_event的Handler和register到了MainEngine中去。

process_new_portfolio_event

    def process_new_portfolio_event(self, event: Event):
""""""
self.update_portfolio_combo() def update_portfolio_combo(self):
""""""
if not self.portfolio_combo.isEnabled():
return self.portfolio_combo.clear()
portfolio_names = self.option_engine.get_portfolio_names()
self.portfolio_combo.addItems(portfolio_names)

根据handler的调用来更新期权产品的列表

calculate_underlying_adjustment


self.chain_button.clicked.connect(self.calculate_underlying_adjustment)
    def calculate_underlying_adjustment(self):
""""""
portfolio = self.option_engine.get_portfolio(self.portfolio_name) for chain in portfolio.chains.values():
chain.calculate_underlying_adjustment()

我们看到 快速交易点击以后,会执行从引擎中获得期权产品的数据,然后执行calculate_underlying_adjustment()方法,要继续深入下去,我们有几个方向:

  1. market_monitor
  2. greeks_monitor
  3. manual_trader
  4. option_engine
  5. calculate_underlying_adjustment

我们还是从周围向心脏的方式学习,先看看几个窗体,然后随后深入引擎的代码学习

market_monitor

class OptionMarketMonitor(MonitorTable):

    def __init__(self, option_engine: OptionEngine, portfolio_name: str):

    def init_ui(self):

    def register_event(self):

    def process_tick_event(self, event: Event):

    def process_trade_event(self, event: Event):

    def process_position_event(self, event: Event):

    def update_pos(self, vt_symbol: str):

    def update_price(self, vt_symbol: str):

    def update_impv(self, vt_symbol: str):

    def update_greeks(self, vt_symbol: str):

    def scroll_to_middle(self):

    def resizeEvent(self, event: QtGui.QResizeEvent):

我们看到 OptionMarketMonitor继承了MonitorTable,而MonitorTable基本上和框架里面的MonitorBase如出一辙。其实大量代码几乎可以重用。

我们先来看看这个类的具体代码,最值得琢磨的其实是这个

    def register_event(self):
""""""
self.signal_tick.connect(self.process_tick_event)
self.signal_trade.connect(self.process_trade_event)
self.signal_position.connect(self.process_position_event) self.event_engine.register(EVENT_TICK, self.signal_tick.emit)
self.event_engine.register(EVENT_TRADE, self.signal_trade.emit)
self.event_engine.register(EVENT_POSITION, self.signal_position.emit)
def __init__(self, option_engine: OptionEngine, portfolio_name: str):
""""""
super().__init__() self.option_engine = option_engine
self.event_engine = option_engine.event_engine
self.portfolio_name = portfolio_name

把处理tick事件,交易事件,仓位事件都和OptionEngine连接起来。

而这些处理的Handler无非根据信息改变界面,就不一一研究。

其他窗体

class OptionManualTrader(QtWidgets.QWidget):
def __init__(self, option_engine: OptionEngine, portfolio_name: str):
""""""
super().__init__() self.option_engine = option_engine
self.main_engine: MainEngine = option_engine.main_engine
self.event_engine: EventEngine = option_engine.event_engine

我们可以看到窗体不但对自己的引擎OptionEngine,而且也对mainEngin和EventEngine有所调用。

 def send_order(self):
""""""
symbol = self.symbol_line.text()
contract = self.contracts.get(symbol, None)
if not contract:
return price_text = self.price_line.text()
volume_text = self.volume_line.text() if not price_text or not volume_text:
return price = float(price_text)
volume = int(volume_text)
direction = Direction(self.direction_combo.currentText())
offset = Offset(self.offset_combo.currentText()) req = OrderRequest(
symbol=contract.symbol,
exchange=contract.exchange,
direction=direction,
type=OrderType.LIMIT,
offset=offset,
volume=volume,
price=price
)
self.main_engine.send_order(req, contract.gateway_name)

整个是通过main_engin来下单的。而在分析主引擎的时候我们知道send_order正是通过gateway_name来下单的。

而gateway_name来自contract合约

而合约来自main_engin

    def init_contracts(self):
""""""
contracts = self.main_engine.get_all_contracts()
for contract in contracts:
self.contracts[contract.symbol] = contract

我们可以想象得到。而main_engine中合约的信息又来自OmsEngine 指定管理系统 (Order Manage System)

接下来我们要继续深入就必须深入到引擎的内容了。

vnpy源码阅读学习(9)回到OptionMaster的更多相关文章

  1. vnpy源码阅读学习(1):准备工作

    vnpy源码阅读学习 目标 通过阅读vnpy,学习量化交易系统的一些设计思路和理念. 通过阅读vnpy学习python项目开发的一些技巧和范式 通过vnpy的设计,可以用python复现一个小型简单的 ...

  2. vnpy源码阅读学习(5):关于MainEngine的代码阅读

    关于MainEngine的代码阅读 在入口文件中,我们看到了除了窗体界面的产生,还有关于MainEngine和EventEngin部分.今天来学习下MainEngine的代码. 首先在run代码中,我 ...

  3. vnpy源码阅读学习(4):自己写一个类似vnpy的UI框架

    自己写一个类似vnpy的界面框架 概述 通过之前3次对vnpy的界面代码的研究,我们去模仿做一个vn.py的大框架.巩固一下PyQt5的学习. 这部分的代码相对来说没有难度和深度,基本上就是把PyQt ...

  4. vnpy源码阅读学习(8):关于app

    关于app 在入口程序中,我们看到了把 gateway,app, 各类的engine都添加到mainEngine中来.不难猜测gateway主要是处理跟外部的行情,接口各方面的代码,通过别人的文章也不 ...

  5. vnpy源码阅读学习(3):学习vnpy的界面的实现

    学习vnpy的界面的实现 通过简单的学习了PyQt5的一些代码以后,我们基本上可以理解PyQt的一些用法,下面让我们来先研究下vnpy的UI部分的代码. 首先回到上一节看到的run.py(/vnpy/ ...

  6. vnpy源码阅读学习(2):学习PyQt5

    PyQt5的学习 花费了一个下午把PyQt5大概的学习了下.找了一个教程 PyQt5教程 跟着挨着把上面的案例做了一遍,大概知道PyQt5是如何生成窗体,以及控件的.基本上做到如果有需求要实现,查查手 ...

  7. vnpy源码阅读学习(7):串在一起

    串在一起 我们已经分析了UI.MainEngine.EventEngine.然后他们几个是如何发挥作用的呢?我总结了一张图: 我们来具体的看看UI部分是如何跟EventEngine穿插起来的 \exa ...

  8. Spring源码阅读学习一

    昨天抽时间阅读Spring源码,先从spring 4.x的core包开始吧,除了core和util里,首当其冲的就是asm和cglib. 要实现两个类实例之间的字段的复制功能: 多年之前用C#,因为阅 ...

  9. requests源码阅读学习笔记

    0:此文并不想拆requests的功能,目的仅仅只是让自己以后写的代码更pythonic.可能会涉及到一部分requests的功能模块,但全看心情. 1.另一种类的初始化方式 class Reques ...

随机推荐

  1. Windows系统向Ubuntu传输文件

    PuTTY传输: 安装PuTTY,然后将PuTTY安装目录下的pscp.exe文件拷贝到/Windows/System32/目录下,在cmd控制台执行命令: # pscp 要传输的文件路径 ubunt ...

  2. [noip模拟]种花<快速幂+结论>

    描述: OI太可怕了,我决定回家种田.我在后院里开辟了一块圆形的花圃,准备种花.种花是一种艺术,通过一定技术手法,花材的排列组合会让花变得更加的赏心悦目,这就是花艺.当然你知道,我在种田之前是OIer ...

  3. Python第十二章-多进程和多线程02-多线程

    接上一章,进程和线程之间可以存在哪些形式呢? 1 单进程单线程:一个人在一个桌子上吃菜. 2 单进程多线程:多个人在同一个桌子上一起吃菜. 3 多进程单线程:多个人每个人在自己的桌子上吃菜. 多线程的 ...

  4. Oracle ROWNUM用法

    很多朋友应该跟我一样有个疑问,为什么rownum > 5 的时候会查不到一条数据,用rownum < 5就可以查到数据,明明查询所有的时候rownum有很多啊,小朋友,你是不是有很多问号? ...

  5. canvas 悬浮效果

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. 1012 The Best Rank (25 分)

    To evaluate the performance of our first year CS majored students, we consider their grades of three ...

  7. 数据挖掘 决策树 Decision tree

    数据挖掘-决策树 Decision tree 目录 数据挖掘-决策树 Decision tree 1. 决策树概述 1.1 决策树介绍 1.1.1 决策树定义 1.1.2 本质 1.1.3 决策树的组 ...

  8. 5个最佳WordPress通知栏插件

    作者:品博客 链接:https://blog.pingbook.top/328/ 来源:品博客 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. WordPress通知栏可有效地将 ...

  9. Nginx知多少系列之(二)安装

    目录 1.前言 2.安装 3.配置文件详解 4.Linux下托管.NET Core项目 5.Linux下.NET Core项目负载均衡 6.Linux下.NET Core项目Nginx+Keepali ...

  10. 【php】面向对象(四)

    知识点:ai一. a => abstract(抽象类) a) 抽象类的修饰符,修饰类和成员方法 b) 注意:被修饰的类不能被实例化,被修饰的方法不能有程序体 c) 如果某一个类使用abstrac ...