vnpy source reading learning: about app

Keywords: Python Programming

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

abc module in Python

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

Python getattr() function

python partial function

Through the above code, we have roughly combed the following ideas.as follows

Posted by _spaz on Sun, 29 Mar 2020 21:24:55 -0700