使用ib_insync进行多线程

时间:2019-05-14 19:36:19

标签: python multithreading

我正在使用ib_insync API请求实时市场数据,然后将其存储在SQL Server中。我想使用多线程来完成此操作,因为我请求的股票代码请求列表太长。当我尝试执行以下代码时,我收到错误消息onPendingTickers(),缺少1个必需的位置参数:“ tickers”。但是,股票行情是IB类的一种方法。

import threading 
from IPython.display import display, clear_output
import pandas as pd
from ib_insync import *
util.startLoop()
import datetime
import urllib.request
from sqlalchemy import create_engine
import pyodbc
import numpy
import threading 
import sys
from queue import Queue
#sys.stdout = open('log_fx.txt', 'w')
##Connections to Database
params = urllib.parse.quote_plus("DRIVER={SQL Server};SERVER=52.168.175.133;Database=DARIUSH;UID=dariush;PWD=success@HPDI**17")
engine = create_engine("mssql+pyodbc:///?odbc_connect=%s" % params, echo=False,fast_executemany = True) #set echo = True to print all sql statements sent to server
conn = engine.connect()
ib = IB()
ib.connect('127.0.0.1', 4002, clientId=7)
contracts = [Forex(pair) for pair in ('EURUSD', 'GBPUSD', 'NZDUSD', 'AUDUSD')]
#    ib.qualifyContracts(*contracts)

## Requesting Market Data  
for contract in contracts:
    ib.reqMktData(contract, '', False, False)

## DataFrame Definitions   
df = pd.DataFrame(
    index=[c.pair() for c in contracts],
    columns=[ 'Symbol','bid', 'ask'])    
df1 = pd.DataFrame( index=[c.pair() for c in contracts],columns = ['SystemTime'])
df2 = pd.DataFrame( index=[c.pair() for c in contracts],columns = ['Symbol','bid','ask','SystemTime'])
df3 = pd.DataFrame()
df4 = pd.DataFrame()
df5 = pd.DataFrame()
## Function to store the incoming ticks in a DataFrame and write that DataFrame to SQL table
def onPendingTickers(q,tickers):
    global df,df1,df2,df3,df4,df5 
    for t in tickers:
        df.loc[t.contract.pair()] = (t.contract.pair(),
             t.bid, t.ask)    
#        clear_output(wait=True)
    df1['SystemTime'] = pd.Series([datetime.datetime.now()] * len(df),index = [c.pair() for c in contracts])                

    df2 = pd.concat([df,df1],axis = 1)
    df2['SystemTime'] = pd.to_datetime(df2['SystemTime'])
    df2.reset_index(drop=True, inplace=True)
    q.put(df2)
#    if df.isnull().any().any() == False:  

def write_toDB(q):
    global df,df1,df2,df3,df4,df5
    start = datetime.datetime.now()
    df2 = q.get()
    if len(df3) > 0:
        df4 =  df2[(df2['bid'].values <= df2['ask'].values) & (0.9*df3['bid'].values <= df2['bid'].values)  & (df2['bid']<= 1.1*df3['bid'].values) & (0.9*df3['ask'].values <= df2['ask'].values) & (df2['ask'] <= 1.1*df3['ask'].values)]    
        df4 = df4.dropna(how = 'any')
        print(df4,'df4')  
#        df4.to_sql('FXtest_tick',conn,if_exists = 'append',index= False,method = 'multi',chunksize = 4)       
#        df2.to_csv('tickData.csv',header=False,index = False,mode = 'a' )
    else:
        df5 = df2.dropna(how = 'any')
#        df5.to_sql('FXtest_tick',conn,if_exists = 'append',index= False,method = 'multi',chunksize = 4) 
        print(df5,'df5')      
    df3 = df2
    print('time diff',datetime.datetime.now() - start) 

    q.task_done()



if __name__ == "__main__":
    # creating thread
    q = Queue() # you were missing the ()
    onPendingTickers(q)
    # q is now full
    workers = 10
    thread_list = []
    for i in range(workers):
        t = threading.Thread(target=write_toDB, args=[q])
        t.start()
        thread_list.append(t)

    q.join()

    for thread in thread_list:
        thread.join()
    ## Timer to keep the connection open to IB for inflow of data
    ib.pendingTickersEvent += onPendingTickers
    ib.sleep(23400)
    ib.pendingTickersEvent -= onPendingTickers
    ib.disconnect()

1 个答案:

答案 0 :(得分:0)

对合同中的合同使用以下代码:

tickers = [ib.reqMktData(contract, '', False, False)]

不需要这行代码onPendingTickers(q)

ib.pendingTickersEvent += onPendingTickers是对onPendingTickers的默认调用