import time
from tcoreapi_mq import * 
import tcoreapi_mq
import threading

g_TradeZMQKeepAlive = None
g_QuoteZMQKeepAlive = None
g_TradeZMQ = None
g_QuoteZMQ = None
g_TradeSession = ""
g_QuoteSession = ""
ReportID=""

#实时行情回调
def OnRealTimeQuote(symbol):
    print("实时行情",symbol["HighPrice"])
#实时Greeks回调
def OnGreeks(greek):
    print("实时Greeks",greek)
#已登入资金账户变更
def OnGetAccount(account):
    print(account["BrokerID"])
#实时委托回报消息
def OnexeReport(report):
    global ReportID
    print("OnexeReport:", report["ReportID"])
    ReportID=report["ReportID"]
    return None
#实时成交回报回调
def RtnFillReport(report):
    print("RtnFillReport:", report["ReportID"])
#查询当日历史委托回报回调
def ShowEXECUTIONREPORT(ZMQ,SessionKey,reportData):
    if reportData["Reply"] == "RESTOREREPORT":
        Orders = reportData["Orders"]
        if len(Orders) == 0:
            return
        last = ""
        for data in Orders:
            last = data
            print("查询回报",data)
        reportData = g_TradeZMQ.restore_report(SessionKey,last["QryIndex"])
        ShowEXECUTIONREPORT(g_TradeZMQ,SessionKey,reportData)
#查询当日历史委托成交回调
def ShowFillReport(ZMQ,SessionKey,reportData):
    if reportData["Reply"] == "RESTOREFILLREPORT":
        Orders = reportData["Orders"]
        if len(Orders) == 0:
            return

        last = ""
        for data in Orders:
            last = data
            print("查询成交回报",data)
        reportData = g_TradeZMQ.restore_report(SessionKey,last["QryIndex"])
        ShowFillReport(g_TradeZMQ,SessionKey,reportData)
#查询持仓消息回调
def ShowPOSITIONS(ZMQ,SessionKey,AccountMask,positionData):
    if positionData["Reply"] == "POSITIONS":
        position = positionData["Positions"]
        if len(position) == 0:
            return

        last = ""
        for data in position:
            last = data
            print("持仓:" + data["Symbol"])

        positionData = g_TradeZMQ.position(SessionKey,AccountMask,last["QryIndex"])
        ShowPOSITIONS(g_TradeZMQ,SessionKey,AccountMask,positionData)


#交易消息接收
def trade_sub_th(obj,sub_port,filter = ""):
    socket_sub = obj.context.socket(zmq.SUB)
    #socket_sub.RCVTIMEO=5000           #ZMQ超时时间设定
    socket_sub.connect("tcp://127.0.0.1:%s" % sub_port)
    socket_sub.setsockopt_string(zmq.SUBSCRIBE,filter)
    while True:
        message =  socket_sub.recv()
        if message:
            message = json.loads(message[:-1])
            #print("in trade message",message)
            if(message["DataType"] == "ACCOUNTS"):
                for i in message["Accounts"]:
                    OnGetAccount(i)
            elif(message["DataType"] == "EXECUTIONREPORT"):
                OnexeReport(message["Report"])
            elif(message["DataType"] == "FILLEDREPORT"):
                RtnFillReport(message["Report"])

#行情消息接收
def quote_sub_th(obj,sub_port,filter = ""):
    socket_sub = obj.context.socket(zmq.SUB)
    #socket_sub.RCVTIMEO=7000   #ZMQ超时时间设定
    socket_sub.connect("tcp://127.0.0.1:%s" % sub_port)
    socket_sub.setsockopt_string(zmq.SUBSCRIBE,filter)
    while(True):
        message = (socket_sub.recv()[:-1]).decode("utf-8")
        index =  re.search(":",message).span()[1]  # filter
        message = message[index:]
        message = json.loads(message)
        #for message in messages:
        if(message["DataType"]=="REALTIME"):
            OnRealTimeQuote(message["Quote"])
        elif(message["DataType"]=="GREEKS"):
            OnGreeks(message["Quote"])
        elif(message["DataType"]=="TICKS" or message["DataType"]=="1K" or message["DataType"]=="DK" ):
            #print("@@@@@@@@@@@@@@@@@@@@@@@",message)
            strQryIndex = ""
            while(True):
                History_obj = {
                    "Symbol": message["Symbol"],
                    "SubDataType":message["DataType"],
                    "StartTime" : message["StartTime"],
                    "EndTime" : message["EndTime"],
                    "QryIndex" : strQryIndex
                }
                s_history = obj.get_history(g_QuoteSession,History_obj)
                historyData = s_history["HisData"]
                if len(historyData) == 0:
                    break

                last = ""
                for data in historyData:
                    last = data
                    print("历史行情：Time:%s, Volume:%s, QryIndex:%s" % (data["Time"], data["Volume"], data["QryIndex"]))
                
                strQryIndex = last["QryIndex"]
                    
    return


def main():

    global g_TradeZMQ
    global g_QuoteZMQ
    global g_TradeSession
    global g_QuoteSession

    #登入
    g_TradeZMQ = tcore_zmq("ZMQ","8076c9867a372d2a9a814ae710c256e2")
    g_QuoteZMQ = tcore_zmq("ZMQ","8076c9867a372d2a9a814ae710c256e2")
    
    t_data = g_TradeZMQ.trade_connect("")
    q_data = g_QuoteZMQ.quote_connect("")
    print(t_data)
    print(q_data)

    if q_data["Success"] != "OK":
        print("[quote]connection failed")
        return

    if t_data["Success"] != "OK":
        print("[trade]connection failed")
        return

    g_TradeSession = t_data["SessionKey"]
    g_QuoteSession = q_data["SessionKey"]

    g_TradeZMQKeepAlive = KeepAliveHelper(t_data["SubPort"], g_TradeSession, g_TradeZMQ)
    g_QuoteZMQKeepAlive = KeepAliveHelper(q_data["SubPort"], g_QuoteSession, g_QuoteZMQ)

    #登出
    #q_logout= g_QuoteZMQ.quote_logout(q_data["SessionKey"])
    #print(q_logout)
    #t_logout= g_TradeZMQ.trade_logout(t_data["SessionKey"])
    #print(t_logout)
    #g_TradeZMQKeepAlive.Close()
    #g_QuoteZMQKeepAlive.Close()

    #查询指定合约信息
    print("查询指定合约：",g_QuoteZMQ.QueryInstrumentInfo(g_QuoteSession,"TC.O.SSE.510050.202012.C.3.6"))
    #查询指定类型合约列表
    #期货：Future
    #期权：Options
    #证券：Stock
    print("查询合约：",g_QuoteZMQ.QueryAllInstrumentInfo(g_QuoteSession,"Stock"))

#####################################################################行情################################################
    #建立一个行情线程
    t2 = threading.Thread(target = quote_sub_th,args=(g_QuoteZMQ,q_data["SubPort"],))
    t2.start()
    #实时行情订阅
    #解除订阅
    g_QuoteZMQ.unsubquote(g_QuoteSession,"TC.O.SSE.510050.202012.C.3.6")
    #订阅实时行情
    g_QuoteZMQ.subquote(g_QuoteSession,"TC.O.SSE.510050.202012.C.3.6")

    #实时Greeks订阅
    #解除订阅
    g_QuoteZMQ.unsubgreeks(g_QuoteSession,"TC.O.SSE.510050.202012.C.3.6")
    #订阅实时行情
    g_QuoteZMQ.subgreeks(g_QuoteSession,"TC.O.SSE.510050.202012.C.3.6")


    #历史数据订阅
    History_obj = {
        "Symbol": "TC.O.SSE.510050.202012.C.3.6",
        "SubDataType":"1K",
        "StartTime" : "2020113001",
        "EndTime" : "2020113007"
    }

    #订阅历史数据
    g_QuoteZMQ.sub_history(g_QuoteSession,History_obj)


#######################################################################交易##################################################
    #创建一个交易线程
    t1 = threading.Thread(target = trade_sub_th,args=(g_TradeZMQ,t_data["SubPort"],))
    t1.start()
    #查询已登入资金账户
    accountInfo = g_TradeZMQ.account_lookup(g_TradeSession)
    strAccountMask=""
    if accountInfo != None:
        arrInfo = accountInfo["Accounts"]
        if len(arrInfo) != 0:
            #print("@@@@@@@@@@@:",arrInfo[0],"\n")
            strAccountMask = arrInfo[0]["AccountMask"]
            
            #查询委托记录
            reportData = g_TradeZMQ.restore_report(g_TradeSession,"")
            ShowEXECUTIONREPORT(g_TradeZMQ,g_TradeSession,reportData)
            fillReportData = g_TradeZMQ.RestoreFillReport(g_TradeSession,"")
            ShowFillReport(g_TradeZMQ,g_TradeSession,fillReportData)

            #查询资金
            if strAccountMask !="":
                print(g_TradeZMQ.margin(g_TradeSession,strAccountMask))
            
            #查询持仓
            positionData = g_TradeZMQ.position(g_TradeSession,strAccountMask,"")
            ShowPOSITIONS(g_TradeZMQ,g_TradeSession,strAccountMask,positionData)

            #下单
            orders_obj = {
            "Symbol":"TC.O.SSE.510050.202012.C.3.6",
            "BrokerID":arrInfo[0]['BrokerID'],
            "Account":arrInfo[0]['Account'],
            "Price":"0.0015",
            "TimeInForce":"1",
            "Side":"1",
            "OrderType":"2",
            "OrderQty":"1",
            "PositionEffect":"0"
            }
            s_order = g_TradeZMQ.new_order(g_TradeSession,orders_obj)

            if s_order['Success']=="OK":
                print("下单成功")
            elif s_order['ErrCode']=="-10":
                print("unknow error")
            elif s_order['ErrCode']=="-11":
                print("买卖别错误")
            elif s_order['ErrCode']=="-12":
                print("复式单商品代码解晰错误 ")
            elif s_order['ErrCode']=="-13":
                print("下单账号, 不可下此交易所商品")
            elif s_order['ErrCode']=="-14":
                print("下单错误, 不支持的价格 或 OrderType 或 TimeInForce ")
            elif s_order['ErrCode']=="-15":
                print("不支援证券下单")
            elif s_order['ErrCode']=="-20":
                print("联机未建立")
            elif s_order['ErrCode']=="-22":
                print("价格的 TickSize 错误")
            elif s_order['ErrCode']=="-23":
                print("下单数量超过该商品的上下限 ")
            elif s_order['ErrCode']=="-24":
                print("下单数量错误 ")
            elif s_order['ErrCode']=="-25":
                print("价格不能小于和等于 0 (市价类型不会去检查) ")

            #改单
            reporders_obj={
                "ReportID":"142733892F",
                "ReplaceExecType":"0",
                "Price":"0.021"
                }
            reorder=g_TradeZMQ.replace_order(g_TradeSession,reporders_obj)

            #删单
            print("%%%%%%%%%%%%%%%%%%%%%%%%%",reorder)
            canorders_obj={
                "ReportID":"142921137H",
                }
            canorder=g_TradeZMQ.cancel_order(g_TradeSession,canorders_obj)
            print("%%%%%%%%%%%%%%%%%%%%%%%%%",canorder)

            orders_obj = {
                    "Symbol":"TC.O.SSE.510050A.202103.C.3.746&TC.O.SSE.510050A.202103.C.3.844",
                    "BrokerID":arrInfo[0]['BrokerID'],
                    "Account":arrInfo[0]['Account'],
                    "CombDirection":"2",
                    "Side":"1",
                    "CombinationType":"1",
                    "Volume":"1"
                    }
            g_TradeZMQ.OptComb(g_TradeSession, orders_obj)

            g_TradeZMQ.QueryOptCombOrder(g_TradeSession, strAccountMask, "")

if __name__ == '__main__':
    main()