About app
In the entry program, we see gateways, apps, and various types of engines added to mainEngine.It is not difficult to guess that gateway mainly deals with external situations, interface code in all aspects, and it is not difficult to see that Engine is the core of vnpy through other people's articles, and can handle all aspects such as strategy, retest and so on.We eat persimmon to find a soft pinch, first pick the easiest part to understand and start reading, then gradually think about the hardest part to understand.So start with the APP section.
start
main_engine.add_app(OptionMasterApp)
Now that you have this code in the entry section.So let's start with OptionMasterApp.
Track all the way
#\vnpy\app\option_master\__init__.py class OptionMasterApp(BaseApp): #ellipsis #\vnpy\trader\app.py class BaseApp(ABC): #ellipsis #D:\Python\Python36\Lib\abc.py
APC is a built-in module for python. Let's first learn how to use abc.I found the following tutorials
Through the study of ABC class, we can generally understand that ABC class is an abstract class, equivalent to the concept of other language interfaces.We can understand that BaseApp is an abstract interface.
BaseApp
class BaseApp(ABC): """ Absstract class for app. """ app_name = "" # Unique name used for creating engine and widget app_module = "" # App module string used in import_module app_path = "" # Absolute path of app folder display_name = "" # Name for display on the menu. engine_class = None # App engine class widget_name = "" # Class name of app widget icon_name = "" # Icon file name of app widget
From the interface class of BaseApp, we can see that properties such as app_name, app_moudel, app_path, display_name, engine_class, widget_name, icon_name are defined. It is not difficult to guess that this is a base class that can dynamically extend modules or components.It should be a subclass of all inherited BaseApps that can be dynamically loaded as apps by vnpy.Let's take OptionMasterApp as an example.See how the app part is implemented.
OptionMasterApp
#\vnpy\app\option_master\__init__.py from pathlib import Path from vnpy.trader.app import BaseApp from .engine import OptionEngine, APP_NAME class OptionMasterApp(BaseApp): app_name = APP_NAME app_module = __module__ app_path = Path(__file__).parent display_name = "Option Trading" engine_class = OptionEngine widget_name = "OptionManager" icon_name = "option.ico"
From the path where OptionMasterApp is located, it is not difficult to find that OptionMasterApp is a separate package.It is not difficult to guess that the entire package implements an app for OptionMaster. APP_NAME and u module_ should be the entry to the app and the name of the package.engine_class loads the engine provided to the app.The code for this package is as follows:
Let's first follow the APP_NAME trace to get the base.py code and see some constants defined
APP_NAME = "OptionMaster" EVENT_OPTION_LOG = "eOptionLog" EVENT_OPTION_NEW_PORTFOLIO = "eOptionNewPortfolio" CHAIN_UNDERLYING_MAP = { "510050_O.SSE": "510050", "IO.CFFEX": "IF", "HO.CFFEX": "IH" }
This APP can be loaded by the code that OptionMasterApp app can provide. Let's first put a thread to track OptionMasterApp and let's see how the APP is loaded with this information.Then go back and learn about each of these apps
Back to MainEngine
We know that all Apps are loaded into MainEngine by MainEngine.add_app(), and then all joined Apps can be called by MainEngine.get_all_apps().Then start calling one by one.We just need to look for a reference to MainEngine.get_all_apps().
def init_menu(self): # Get all the configuration information that inherits BaseApp all_apps = self.main_engine.get_all_apps() for app in all_apps: #Packages that introduce.ui in BaseApp moudle s ui_module = import_module(app.app_module + ".ui") #Find widget_name through ui's package widget_class = getattr(ui_module, app.widget_name) func = partial(self.open_widget, widget_class, app.app_name) icon_path = str(app.app_path.joinpath("ui", app.icon_name)) self.add_menu_action( app_menu, app.display_name, icon_path, func ) self.add_toolbar_action( app.display_name, icon_path, func ) def add_menu_action( self, menu: QtWidgets.QMenu, action_name: str, icon_name: str, func: Callable, ): """""" icon = QtGui.QIcon(get_icon_path(__file__, icon_name)) action = QtWidgets.QAction(action_name, self) action.triggered.connect(func) action.setIcon(icon) menu.addAction(action) def add_toolbar_action( self, action_name: str, icon_name: str, func: Callable, ): """""" icon = QtGui.QIcon(get_icon_path(__file__, icon_name)) action = QtWidgets.QAction(action_name, self) action.triggered.connect(func) action.setIcon(icon) self.toolbar.addAction(action) def open_widget(self, widget_class: QtWidgets.QWidget, name: str): """ Open contract manager. """ widget = self.widgets.get(name, None) if not widget: widget = widget_class(self.main_engine, self.event_engine) self.widgets[name] = widget if isinstance(widget, QtWidgets.QDialog): widget.exec_() else: widget.show()
Tutorials on using some of python's built-in functions
Python programming: importlib.import_module dynamic import module
Through the above code, we have roughly combed the following ideas.as follows