【问题标题】:Script doesn't print to console in real time [PYTHON]脚本不会实时打印到控制台 [PYTHON]
【发布时间】:2017-03-22 16:51:26
【问题描述】:

我正在测试如何通过交互式经纪人的 API 和 reqMktData 接收实时数据。该算法通过无限循环运行,允许实时实时流数据,直到我停止脚本。 当我运行它时,它应该按照下面的代码中指定的方式将数据连续打印到控制台。但是,在我点击“停止当前命令”之前,会打印 nothing。然后我得到一个巨大的数据转储,其中包含自脚本执行以来收到的所有数据。

我尝试了以下解决方案,在脚本开头导入 sys 并在每次打印后刷新输出。但是,这也不起作用:

import sys
sys.stdout.flush()

我正在使用 python 2.7 和 spyder——而且对 python 还是很陌生。

希望有人可以提供帮助!非常感谢任何输入。

我正在测试的脚本:

from ib.ext.Contract import Contract
from ib.ext.Order import Order
from ib.opt import Connection, message
import pandas as pd
import datetime as dt


class AlgoSystem:
    def __init__(self, symbol, qty, resample_interval,
                 averaging_period=5, port=7496):
        self.client_id = 1
        self.order_id = 1
        self.qty = qty
        self.symbol_id, self.symbol = 0, symbol
        self.resample_interval = resample_interval
        self.averaging_period = averaging_period
        self.port = port
        self.tws_conn = None
        self.bid_price, self.ask_price = 0, 0
        self.last_prices = pd.DataFrame(columns=[self.symbol_id])
        self.average_price = 0
        self.account_code = None

    def error_handler(self, msg):
        if msg.typeName == "error" and msg.id != -1:
            print "Server Error:", msg


    def tick_event(self, msg):
        if msg.field == 1:
            self.bid_price = msg.price
        elif msg.field == 2:
            self.ask_price = msg.price
        elif msg.field == 4:
            self.last_prices.loc[dt.datetime.now()] = msg.price
            resampled_prices = \
                self.last_prices.resample(self.resample_interval,
                                          how='last',
                                          fill_method="ffill")
            self.average_price = resampled_prices.tail(
                self.averaging_period).mean()[0]

        print dt.datetime.now(), "average:", self.average_price, \
            "bid:", self.bid_price, "ask:", self.ask_price



    def create_contract(self, symbol, sec_type, exch, prim_exch, curr):
        contract = Contract()
        contract.m_symbol = symbol
        contract.m_secType = sec_type
        contract.m_exchange = exch
        contract.m_primaryExch = prim_exch
        contract.m_currency = curr
        return contract


    def request_market_data(self, symbol_id, symbol):
        contract = self.create_contract(symbol,
                                        'STK',
                                        'SMART',
                                        'SMART',
                                        'USD')
        self.tws_conn.reqMktData(symbol_id, contract, '', False)
        time.sleep(1)

    def cancel_market_data(self, symbol):
        self.tws_conn.cancelMktData(symbol)
        time.sleep(1)


    def connect_to_tws(self):
        self.tws_conn = Connection.create(port=self.port,
                                          clientId=self.client_id)
        self.tws_conn.connect()

    def disconnect_from_tws(self):
        if self.tws_conn is not None:
            self.tws_conn.disconnect()

    def register_callback_functions(self):
        # Assign error handling function.
        self.tws_conn.register(self.error_handler, 'Error')

        # Register market data events.
        self.tws_conn.register(self.tick_event,
                               message.tickPrice,
                               message.tickSize)

    def start(self):
        try:
            self.connect_to_tws()
            self.register_callback_functions()
            self.request_market_data(self.symbol_id, self.symbol)

            while True:
                time.sleep(1)

        except Exception, e:
            print "Error:", e
            self.cancel_market_data(self.symbol)

        finally:
            print "disconnected"
            self.disconnect_from_tws()

if __name__ == "__main__":
    system = AlgoSystem("FB", 100, "30s", 5)
    system.start()

【问题讨论】:

    标签: python printing flush ibpy


    【解决方案1】:

    我对交互式代理 API 一无所知,但我猜您的 start 方法需要更改为:

    def start(self):
    
        try:
            self.connect_to_tws()
            self.register_callback_functions()
            while True:
                self.request_market_data(self.symbol_id, self.symbol)
                time.sleep(1)
    
        except Exception, e:
            print "Error:", e
            self.cancel_market_data(self.symbol)
    
        finally:
            print "disconnected"
            self.disconnect_from_tws()
    

    目前您的无限循环只是反复休眠。我认为您希望 request_market_data 位于 inside while 循环中。

    【讨论】:

    • 您好,感谢您的建议。但是,这种修改只会导致程序不断连接,获取一些数据并断开连接。在代码只连接一次之前,reqMktData 开启了实时数据的开关,并且创建了 tick_event 来处理每条包含刻度信息的传入消息。
    • while 循环中唯一的东西是time.sleep(1) 命令。这就是为什么它会阻塞,直到你按 ctrl-C。您需要在收集数据的循环中放入一些东西。如果你不想连续连接和断开,那么把connect和disconnect方法放在循环外面,如果可以的话,把request_market_data方法放在循环里面
    • Alex 很可能是对的,你不能只是休眠你的程序。看看stackoverflow.com/a/43005947/2855515 我解释了一些异步的东西。
    猜你喜欢
    • 2020-06-29
    • 1970-01-01
    • 2013-12-22
    • 2012-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-06
    • 2012-02-07
    相关资源
    最近更新 更多