回到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. coding++ :局部 Loading 加载效果

    $("<div id='shade' style='opacity:0.85;background:white'></div><img src='${ctx}/ ...

  2. spring bean的装载过程简略赏析

    spring一个bean的容器,它从这个最基本的功能进而扩展出AOP,transaction,cache,schedule,data等等,将业务与框架代码解耦,让我们可以将大部分精力投入到业务代码中, ...

  3. 吴恩达DeepLearning.ai的Sequence model作业Dinosaurus Island

    目录 1 问题设置 1.1 数据集和预处理 1.2 概览整个模型 2. 创建模型模块 2.1 在优化循环中梯度裁剪 2.2 采样 3. 构建语言模型 3.1 梯度下降 3.2 训练模型 4. 结论   ...

  4. Python turtle库的应用——蛇

    turtle库介绍 1.Turtle中的turtle.setup()函数用于启动一个图形窗口,它有四个参数 turtle.setup(width, height, startx, starty) 分别 ...

  5. CAP定理和BASE理论

    CAP定理和BASE理论 标签(空格分隔): 操作系统 CAP定理 CAP定理: 一个分布式系统最多只能满足一致性 (Consistency), 可用性(Availability)和分区容错性(Par ...

  6. Shell脚本的编写及测试

                                                      Shell脚本的编写及测试 1.1问题 本例要求两个简单的Shell脚本程序,任务目标如下: 编写一 ...

  7. GitHub 热点速览 Vol.15:Background-Matting 让你秒变专业抠图师

    作者:HelloGitHub-小鱼干 摘要:如果要选一个词来概述上周的热点,春风拂过,应该是一个不错的词.新项目像春天冒出的枝芽,朝气蓬勃,虽然获得的 star 不如之前三维 Vim 抢眼,但胜在多姿 ...

  8. 电商平台--Mysql主从搭建(2)

    Master上授权从库: ```grant replication slave on *.* to slave1@ip identified by 'password';``` 基于数据库hotcop ...

  9. 【高并发】你知道吗?大家都在使用Redisson实现分布式锁了!!

    写在前面 忘记之前在哪个群里有朋友在问:有出分布式锁的文章吗-@冰河?我的回答是:这周会有,也是[高并发]专题的.想了想,还是先发一个如何使用Redisson实现分布式锁的文章吧?为啥?因为使用Red ...

  10. SQLAlchemy查询

    SQLAlchemy查询 结果查询: from databases.wechat import User from config import session def search(): result ...