コード例 #1
0
ファイル: app.py プロジェクト: stockServ/ctpbee
    def init_interface(self):
        if self.config.get("PATTERN",
                           "real") == "real" and not self._init_interface:
            self.active = True
            if "CONNECT_INFO" in self.config.keys():
                info = self.config.get("CONNECT_INFO")
            else:
                raise ConfigError(message="没有相应的登录信息", args=("没有发现登录信息", ))
            MdApi, TdApi = Interface.get_interface(self)
            if self.config.get("MD_FUNC"):
                self.market = MdApi(self.app_signal)
                self.market.connect(info)

            if self.config.get("TD_FUNC"):
                self.trader = TdApi(self.app_signal)
                self.trader.connect(info)
            self._init_interface = True
        elif self.config.get("PATTERN",
                             "real") == "looper" and not self._init_interface:

            self.config["INTERFACE"] = "looper"
            Market, Trader = Interface.get_interface(app=self)
            self.trader = Trader(self.app_signal, self)
            self.market = Market(self.app_signal)
            self._init_interface = True
コード例 #2
0
    def __init__(self,
                 name: Text,
                 import_name,
                 engine_method: str = "thread",
                 instance_path=None):
        """ 初始化 """
        self.name = name
        self.import_name = import_name
        if engine_method == "thread":
            self.event_engine = EventEngine()
            self.recorder = Recorder(self, self.event_engine)
        elif engine_method == "async":
            self.event_engine = AsyncEngine()
            self.recorder = AsyncRecorder(self, self.event_engine)
        else:
            raise TypeError("引擎参数错误,只支持thread和async,请检查代码")
        if instance_path is None:
            instance_path = self.auto_find_instance_path()
        elif not os.path.isabs(instance_path):
            raise ValueError(
                'If an instance path is provided it must be absolute.'
                ' A relative path was given instead.')
        self.risk_gateway = RiskLevel(self)

        self.instance_path = instance_path
        self.config = self.make_config()
        self.interface = Interface()
        _app_context_ctx.push(self.name, self)
コード例 #3
0
    def _load_ext(self):
        """根据当前配置文件下的信息载入行情api和交易api,记住这个api的选项是可选的"""
        self.active = True
        if "CONNECT_INFO" in self.config.keys():
            info = self.config.get("CONNECT_INFO")
        else:
            raise ConfigError(message="没有相应的登录信息", args=("没有发现登录信息",))
        MdApi, TdApi = Interface.get_interface(self)
        if self.config.get("MD_FUNC"):
            self.market = MdApi(self.event_engine)
            self.market.connect(info)

        if self.config.get("TD_FUNC"):
            if self.config['INTERFACE'] == "looper":
                self.trader = TdApi(self.event_engine, self)
            else:
                self.trader = TdApi(self.event_engine)
            self.trader.connect(info)

        show_me = graphic_pattern(__version__, self.engine_method)
        print(show_me)
        if self.refresh:
            if self.r is not None:
                self.r_flag = False
                sleep(self.config['REFRESH_INTERVAL'] + 1.5)
                self.r = Thread(target=refresh_query, args=(self,),daemon=True)
                self.r.start()
            else:
                self.r = Thread(target=refresh_query, args=(self,), daemon=True)
                self.r.start()
            self.r_flag = True
コード例 #4
0
ファイル: app.py プロジェクト: tbmilk/ctpbee
    def start(self, log_output=True, debug=False):
        """
        开启处理
        :param log_output: 是否输出log信息
        :param debug: 是否开启调试模式 ----> 等待完成
        :return:
        """
        if self.config.get("PATTERN") == "real":

            def running_timer(common_signal):
                while True:
                    event = Event(type=EVENT_TIMER)
                    common_signal.timer_signal.send(event)
                    sleep(self.config['TIMER_INTERVAL'])

            self.timer = Thread(target=running_timer, args=(common_signals, ))
            self.timer.start()

            self.config["LOG_OUTPUT"] = log_output
            self._running(logout=log_output)
        elif self.config.get("PATTERN") == "looper":
            self.config["INTERFACE"] = "looper"
            show_me = graphic_pattern(__version__, self.engine_method)
            if log_output:
                print(show_me)
            Trader, Market = Interface.get_interface(app=self)
            self.trader = Trader(self.app_signal, self)
            self.market = Market(self.app_signal)
            print(">>>> 回测接口载入成功")
            self._start_looper()
        else:
            raise ValueError("错误的参数, 仅仅支持")
コード例 #5
0
    def _running(self, logout=True):
        """
        根据当前配置文件下的信息载入行情api和交易api
        注意此函数同时会根据构造函数中的refresh参数决定开启定时线程, 向CtpBee里面提供定时查询账户持仓功能
        """
        self.active = True
        if "CONNECT_INFO" in self.config.keys():
            info = self.config.get("CONNECT_INFO")
        else:
            raise ConfigError(message="没有相应的登录信息", args=("没有发现登录信息",))
        show_me = graphic_pattern(__version__, self.engine_method)
        if logout:
            print(show_me)
        MdApi, TdApi = Interface.get_interface(self)
        if self.config.get("MD_FUNC"):
            self.market = MdApi(self.app_signal)
            self.market.connect(info)

        if self.config.get("TD_FUNC"):
            self.trader = TdApi(self.app_signal)
            self.trader.connect(info)

        if self.refresh:
            if self.r is not None:
                self.r_flag = False
                sleep(self.config['REFRESH_INTERVAL'] + 1.5)
                self.r = Thread(target=refresh_query, args=(self,), daemon=True)
                self.r.start()
            else:
                self.r = Thread(target=refresh_query, args=(self,), daemon=True)
                self.r.start()
            self.r_flag = True
コード例 #6
0
ファイル: app.py プロジェクト: sixuerain/ctpbee
 def __init__(self, name: Text, import_name, instance_path=None):
     """ 初始化 """
     self.name = name
     self.import_name = import_name
     self.event_engine = EventEngine()
     if instance_path is None:
         instance_path = self.auto_find_instance_path()
     elif not os.path.isabs(instance_path):
         raise ValueError(
             'If an instance path is provided it must be absolute.'
             ' A relative path was given instead.')
     self.risk_control = RiskController(self.name)
     self.recorder = Recorder(self, self.event_engine)
     self.instance_path = instance_path
     self.config = self.make_config()
     self.interface = Interface()
     _app_context_ctx.push(self.name, self)
コード例 #7
0
class CtpBee(object):
    """
    ctpbee 源于我对于做项目的痛点需求, 旨在开发出一套具有完整api的交易微框架 ,
    在这里你可以看到很多借鉴自flask的设计 , 毕竟本人实在热爱flask ....
    ctpbee提供完整的支持 ,一个CtpBee对象可以登录一个账户 ,
    当你登录多个账户时, 可以通过current_app, 以及switch_app还有 get_app提供完整的支持,
    每个账户对象都拥有单独的发单接口 ,在你实现策略的地方 可以通过上述api实现发单支持,
    当然ctpbee提供了CtpbeeApi 抽象插件 ,继承此插件即可快速载入支持.
    总而言之,希望能够极大的简化目前的开发流程 !
    """

    # 默认配置
    default_config = ImmutableDict(
        dict(LOG_OUTPUT=True,
             TD_FUNC=False,
             INTERFACE="ctp",
             MD_FUNC=True,
             XMIN=[],
             ALL_SUBSCRIBE=False,
             SHARE_MD=False,
             ENGINE_METHOD="thread"))
    config_class = Config
    import_name = None
    # 数据记录载体
    __active = False

    # 交易api与行情api
    market = None
    trader = None

    # 插件系统
    # todo :等共享内存块出来了 是否可以尝试在外部进行
    extensions = {}

    def __init__(self,
                 name: Text,
                 import_name,
                 engine_method: str = "thread",
                 instance_path=None):
        """ 初始化 """
        self.name = name
        self.import_name = import_name
        if engine_method == "thread":
            self.event_engine = EventEngine()
            self.recorder = Recorder(self, self.event_engine)
        elif engine_method == "async":
            self.event_engine = AsyncEngine()
            self.recorder = AsyncRecorder(self, self.event_engine)
        else:
            raise TypeError("引擎参数错误,只支持thread和async,请检查代码")
        if instance_path is None:
            instance_path = self.auto_find_instance_path()
        elif not os.path.isabs(instance_path):
            raise ValueError(
                'If an instance path is provided it must be absolute.'
                ' A relative path was given instead.')
        self.risk_gateway = RiskLevel(self)

        self.instance_path = instance_path
        self.config = self.make_config()
        self.interface = Interface()
        _app_context_ctx.push(self.name, self)

    def make_config(self):
        """ 生成class类"""
        defaults = dict(self.default_config)
        return self.config_class(self.instance_path, defaults)

    def auto_find_instance_path(self):
        prefix, package_path = find_package(self.import_name)
        if prefix is None:
            return os.path.join(package_path)
        return os.path.join(prefix, 'var', self.name + '-instance')

    @property
    def td_login_status(self):
        """ 交易 API 都应该实现td_status"""
        return self.trader.td_status

    @property
    def md_login_status(self):
        """ 行情 API 都应该实现md_status"""
        return self.market.md_status

    def _load_ext(self):
        """根据当前配置文件下的信息载入行情api和交易api,记住这个api的选项是可选的"""
        self.__active = True
        if "CONNECT_INFO" in self.config.keys():
            info = self.config.get("CONNECT_INFO")
        else:
            raise ConfigError(message="没有相应的登录信息", args=("没有发现登录信息", ))
        MdApi, TdApi = self.interface.get_interface(self)
        if self.config.get("MD_FUNC"):
            self.market = MdApi(self.event_engine)
            self.market.connect(info)

        if self.config.get("TD_FUNC"):
            self.trader = TdApi(self.event_engine)
            self.trader.connect(info)
            sleep(0.5)

    @locked_cached_property
    def name(self):
        if self.import_name == '__main__':
            fn = getattr(sys.modules['__main__'], '__file__', None)
            if fn is None:
                return '__main__'
            return os.path.splitext(os.path.basename(fn))[0]
        return self.import_name

    def start(self, log_output=True):
        """开始"""
        if not self.event_engine.status:
            self.event_engine.start()
        self.config["LOG_OUTPUT"] = log_output
        self._load_ext()

    def stop(self):
        """ 停止运行 """
        if self.event_engine.status:
            self.event_engine.stop()

    @check(type="trader")
    def send_order(self, order_req: OrderRequest) -> AnyStr:
        """发单"""
        result = self.risk_gateway.send(self)
        if False in result:
            event = Event(type=EVENT_LOG, data="风控阻止下单")
            self.event_engine.put(event)
            return
        send_monitor.send(order_req)
        return self.trader.send_order(order_req)

    @check(type="trader")
    def cancel_order(self, cancle_req: CancelRequest):
        """撤单"""
        cancle_monitor.send(cancle_req)
        self.trader.cancel_order(cancle_req)

    @check(type="market")
    def subscribe(self, symbol: AnyStr):
        """订阅行情"""
        if "." in symbol:
            symbol = symbol.split(".")[1]
        return self.market.subscribe(symbol)

    @check(type="trader")
    def query_position(self):
        """查询持仓"""
        return self.trader.query_position()

    @check(type="trader")
    def transfer(self, req, type):
        """
        req currency attribute
        ["USD", "HKD", "CNY"]
        :param req:
        :param type:
        :return:
        """
        self.trader.transfer(req, type=type)

    @check(type="trader")
    def query_account_register(self, req):
        self.trader.query_account_register(req)

    @check(type="trader")
    def query_bank_account_money(self, req):
        self.trader.query_bank_account_money(req)

    @check(type="trader")
    def query_transfer_serial(self, req):
        self.trader.query_transfer_serial(req)

    @check(type="trader")
    def query_bank(self):
        pass

    @check(type="trader")
    def query_account(self):
        """查询账户"""
        return self.trader.query_account()

    def remove_extension(self, extension_name: Text) -> None:
        """移除插件"""
        if extension_name in self.extensions:
            del self.extensions[extension_name]

    def add_extension(self, extension: CtpbeeApi):
        """添加插件"""
        if extension.extension_name in self.extensions:
            return
        extension.init_app(self)
        self.extensions[extension.extension_name] = extension

    def suspend_extension(self, extension_name):
        extension = self.extensions.get(extension_name, None)
        if not extension:
            return False
        extension.frozen = True
        return True

    def enable_extension(self, extension_name):
        extension = self.extensions.get(extension_name, None)
        if not extension:
            return False
        extension.frozen = False
        return True

    def reload(self):
        """ 重新载入接口 """
        if self.market is not None:
            self.market.close()
        if self.trader is not None:
            self.trader.close()
        self._load_ext()

    def __del__(self):
        """释放账户 安全退出"""
        print("注销")
        if self.market is not None:
            self.market.close()
        if self.trader is not None:
            self.trader.close()
        self.market, self.trader = None, None

        del self.event_engine
コード例 #8
0
    def _load_ext(self):
        """根据当前配置文件下的信息载入行情api和交易api,记住这个api的选项是可选的"""
        self.__active = True
        if "CONNECT_INFO" in self.config.keys():
            info = self.config.get("CONNECT_INFO")
        else:
            raise ConfigError(message="没有相应的登录信息", args=("没有发现登录信息", ))
        MdApi, TdApi = Interface.get_interface(self)
        if self.config.get("MD_FUNC"):
            self.market = MdApi(self.event_engine)
            self.market.connect(info)

        if self.config.get("TD_FUNC"):
            if self.config['INTERFACE'] == "looper":
                self.trader = TdApi(self.event_engine, self)
            else:
                self.trader = TdApi(self.event_engine)
            self.trader.connect(info)

        show_me = \
            f"""
{"*" * 60}                                                               
*                                                          *
*          -------------------------------------           *
*          |                                   |           *
*          |      ctpbee:    {__version__.ljust(16, " ")}  |           *
*          |      work_mode: {self.work_mode.ljust(16, " ")}  |           *
*          |      engine:    {self.engine_method.ljust(16, " ")}  |           *
*          |                                   |           *
*          -------------------------------------           *
*                                                          *
{"*" * 60}                       
         """
        print(show_me)

        # 检查work_mode
        if self.work_mode == "forever":
            """ 7×24小时 """
            # 启动监视器

            if self.p is not None:
                self.p_flag = False
                sleep(1.5)
                self.p = Thread(target=run_forever, args=(self, ))
                self.p.start()

            else:
                self.p = Thread(target=run_forever, args=(self, ))
                self.p.start()
            self.p_flag = True
        else:
            pass

        if self.refresh:
            if self.r is not None:
                self.r_flag = False
                sleep(self.config['REFRESH_INTERVAL'] + 1.5)
                self.r = Thread(target=refresh_query, args=(self, ))
                self.r.start()
            else:
                self.r = Thread(target=refresh_query, args=(self, ))
                self.r.start()
            self.r_flag = True
        self.p_flag = True