[Add] ITapGateway: Added support for Market subscription
[Mod] use newer autocxxpy: make error handing better and make its hint(generated pyi code) better.
This commit is contained in:
parent
06b16cb0b3
commit
c580d3cb76
Binary file not shown.
@ -7,11 +7,12 @@ if typing.TYPE_CHECKING:
|
||||
from .vnitap import *
|
||||
|
||||
|
||||
def set_async_callback_exception_handler(handler: Callable[[Exception, object, str], bool]):
|
||||
def set_async_callback_exception_handler(handler: Callable[[AsyncDispatchException], bool]):
|
||||
"""
|
||||
set a customize exception handler for async callback in this module(pyd)
|
||||
\a handler should return True if it handles that exception,
|
||||
If the return value of \a handler is not True, exception will be re-thrown.
|
||||
|
||||
:note: If the return value of \a handler is not True, exception will be re-thrown.
|
||||
"""
|
||||
...
|
||||
|
||||
@ -179,21 +180,21 @@ class ITapQuoteAPINotify():
|
||||
|
||||
|
||||
|
||||
def OnRspLogin(self, errorCode: int, info: TapAPIQuotLoginRspInfo)->Any:
|
||||
def OnRspLogin(self, errorCode: int, info: TapAPIQuotLoginRspInfo)->None:
|
||||
...
|
||||
def OnAPIReady(self, )->Any:
|
||||
def OnAPIReady(self, )->None:
|
||||
...
|
||||
def OnDisconnect(self, reasonCode: int)->Any:
|
||||
def OnDisconnect(self, reasonCode: int)->None:
|
||||
...
|
||||
def OnRspQryCommodity(self, sessionID: int, errorCode: int, isLast: int, info: TapAPIQuoteCommodityInfo)->Any:
|
||||
def OnRspQryCommodity(self, sessionID: int, errorCode: int, isLast: int, info: TapAPIQuoteCommodityInfo)->None:
|
||||
...
|
||||
def OnRspQryContract(self, sessionID: int, errorCode: int, isLast: int, info: TapAPIQuoteContractInfo)->Any:
|
||||
def OnRspQryContract(self, sessionID: int, errorCode: int, isLast: int, info: TapAPIQuoteContractInfo)->None:
|
||||
...
|
||||
def OnRspSubscribeQuote(self, sessionID: int, errorCode: int, isLast: int, info: TapAPIQuoteWhole)->Any:
|
||||
def OnRspSubscribeQuote(self, sessionID: int, errorCode: int, isLast: int, info: TapAPIQuoteWhole)->None:
|
||||
...
|
||||
def OnRspUnSubscribeQuote(self, sessionID: int, errorCode: int, isLast: int, info: TapAPIContract)->Any:
|
||||
def OnRspUnSubscribeQuote(self, sessionID: int, errorCode: int, isLast: int, info: TapAPIContract)->None:
|
||||
...
|
||||
def OnRtnQuote(self, info: TapAPIQuoteWhole)->Any:
|
||||
def OnRtnQuote(self, info: TapAPIQuoteWhole)->None:
|
||||
...
|
||||
class ITapQuoteAPI():
|
||||
|
||||
@ -438,7 +439,7 @@ TAPIERROR_SUBSCRIBEQUOTE_CONTRACT_MAY_NOT_EXIST: int
|
||||
TAPIERROR_QUOTEFRONT_UNKNOWN_PROTOCOL: int
|
||||
def CreateITapTradeAPI(appInfo: ITapTrade.TapAPIApplicationInfo)->Tuple[ITapTrade.ITapTradeAPI,int]:
|
||||
return "retv","iResult"
|
||||
def FreeITapTradeAPI(apiObj: ITapTrade.ITapTradeAPI)->Any:
|
||||
def FreeITapTradeAPI(apiObj: ITapTrade.ITapTradeAPI)->None:
|
||||
...
|
||||
def GetITapTradeAPIVersion()->str:
|
||||
...
|
||||
@ -450,7 +451,7 @@ def GetITapErrorDescribe(errorCode: int)->str:
|
||||
...
|
||||
def CreateTapQuoteAPI(appInfo: TapAPIApplicationInfo)->Tuple[ITapQuoteAPI,int]:
|
||||
return "retv","iResult"
|
||||
def FreeTapQuoteAPI(apiObj: ITapQuoteAPI)->Any:
|
||||
def FreeTapQuoteAPI(apiObj: ITapQuoteAPI)->None:
|
||||
...
|
||||
def GetTapQuoteAPIVersion()->str:
|
||||
...
|
||||
|
@ -27,7 +27,7 @@ void init_dispatcher(pybind11::module &m)
|
||||
m.def("set_async_callback_exception_handler", &autocxxpy::async_callback_exception_handler::set_handler);
|
||||
|
||||
pybind11::class_<autocxxpy::async_dispatch_exception> c(m, "AsyncDispatchException");
|
||||
c.def_property("what", &autocxxpy::async_dispatch_exception::what, nullptr);
|
||||
c.def_property_readonly("what", &autocxxpy::async_dispatch_exception::what_mutable);
|
||||
c.def_readonly("instance", &autocxxpy::async_dispatch_exception::instance);
|
||||
c.def_readonly("function_name", &autocxxpy::async_dispatch_exception::function_name);
|
||||
|
||||
|
@ -3,11 +3,14 @@
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <optional>
|
||||
#include <iostream>
|
||||
|
||||
#include "brigand.hpp"
|
||||
#include "./brigand.hpp"
|
||||
|
||||
#include "utils/functional.hpp"
|
||||
#include "dispatcher.hpp"
|
||||
#include "./utils/functional.hpp"
|
||||
#include "./dispatcher.hpp"
|
||||
#include "./config/config.hpp"
|
||||
#include "./wrappers/string_array.hpp"
|
||||
|
||||
namespace autocxxpy
|
||||
{
|
||||
@ -28,7 +31,7 @@ namespace autocxxpy
|
||||
template<>
|
||||
struct callback_wrapper<static_cast<int(A::*)(int)>(&A::func2)>
|
||||
{
|
||||
inline static void call(A *instance, float)
|
||||
inline static void call(A *instance, const char *py_func_name, float)
|
||||
{
|
||||
constexpr auto method = static_cast<int(A::*)(int)>(&A::func2);
|
||||
default_callback_wrapper<method>::call(instance, 1);
|
||||
@ -83,7 +86,9 @@ namespace autocxxpy
|
||||
{}
|
||||
pybind11::object instance;
|
||||
std::string function_name;
|
||||
inline const char* what() noexcept
|
||||
|
||||
// mutable version of what() for pybind11 to make it happy
|
||||
inline const char* what_mutable() noexcept
|
||||
{
|
||||
return std::exception::what();
|
||||
}
|
||||
@ -98,7 +103,23 @@ namespace autocxxpy
|
||||
{
|
||||
if (custom_handler)
|
||||
{
|
||||
custom_handler(e);
|
||||
try
|
||||
{
|
||||
custom_handler(e);
|
||||
}
|
||||
catch (pybind11::error_already_set & e2)
|
||||
{
|
||||
std::cerr << "error while calling custom async callback exception handler:" << std::endl;
|
||||
std::cerr << e2.what() << std::endl;
|
||||
std::cerr << "while handling following exception:" << std::endl;
|
||||
std::cerr << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << e.what() << std::endl;
|
||||
std::cerr << "custom async callback exception handler not set." << std::endl;
|
||||
std::cerr << "Call set_async_callback_exception_handler() to set it. " << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,11 +7,12 @@ if typing.TYPE_CHECKING:
|
||||
from .vnitap import *
|
||||
|
||||
|
||||
def set_async_callback_exception_handler(handler: Callable[[Exception, object, str], bool]):
|
||||
def set_async_callback_exception_handler(handler: Callable[[AsyncDispatchException], bool]):
|
||||
"""
|
||||
set a customize exception handler for async callback in this module(pyd)
|
||||
\a handler should return True if it handles that exception,
|
||||
If the return value of \a handler is not True, exception will be re-thrown.
|
||||
|
||||
:note: If the return value of \a handler is not True, exception will be re-thrown.
|
||||
"""
|
||||
...
|
||||
|
||||
@ -1129,105 +1130,105 @@ class ITapTradeAPINotify():
|
||||
|
||||
|
||||
|
||||
def OnConnect(self, )->Any:
|
||||
def OnConnect(self, )->None:
|
||||
...
|
||||
def OnRspLogin(self, errorCode: int, loginRspInfo: ITapTrade.TapAPITradeLoginRspInfo)->Any:
|
||||
def OnRspLogin(self, errorCode: int, loginRspInfo: ITapTrade.TapAPITradeLoginRspInfo)->None:
|
||||
...
|
||||
def OnRtnContactInfo(self, errorCode: int, isLast: int, ContactInfo: str)->Any:
|
||||
def OnRtnContactInfo(self, errorCode: int, isLast: int, ContactInfo: str)->None:
|
||||
...
|
||||
def OnRspRequestVertificateCode(self, sessionID: int, errorCode: int, rsp: ITapTrade.TapAPIRequestVertificateCodeRsp)->Any:
|
||||
def OnRspRequestVertificateCode(self, sessionID: int, errorCode: int, rsp: ITapTrade.TapAPIRequestVertificateCodeRsp)->None:
|
||||
...
|
||||
def OnExpriationDate(self, date: str, days: int)->Any:
|
||||
def OnExpriationDate(self, date: str, days: int)->None:
|
||||
...
|
||||
def OnAPIReady(self, errorCode: int)->Any:
|
||||
def OnAPIReady(self, errorCode: int)->None:
|
||||
...
|
||||
def OnDisconnect(self, reasonCode: int)->Any:
|
||||
def OnDisconnect(self, reasonCode: int)->None:
|
||||
...
|
||||
def OnRspChangePassword(self, sessionID: int, errorCode: int)->Any:
|
||||
def OnRspChangePassword(self, sessionID: int, errorCode: int)->None:
|
||||
...
|
||||
def OnRspAuthPassword(self, sessionID: int, errorCode: int)->Any:
|
||||
def OnRspAuthPassword(self, sessionID: int, errorCode: int)->None:
|
||||
...
|
||||
def OnRspQryTradingDate(self, sessionID: int, errorCode: int, info: ITapTrade.TapAPITradingCalendarQryRsp)->Any:
|
||||
def OnRspQryTradingDate(self, sessionID: int, errorCode: int, info: ITapTrade.TapAPITradingCalendarQryRsp)->None:
|
||||
...
|
||||
def OnRspSetReservedInfo(self, sessionID: int, errorCode: int, info: str)->Any:
|
||||
def OnRspSetReservedInfo(self, sessionID: int, errorCode: int, info: str)->None:
|
||||
...
|
||||
def OnRspQryAccount(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIAccountInfo)->Any:
|
||||
def OnRspQryAccount(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIAccountInfo)->None:
|
||||
...
|
||||
def OnRspQryFund(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIFundData)->Any:
|
||||
def OnRspQryFund(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIFundData)->None:
|
||||
...
|
||||
def OnRtnFund(self, info: ITapTrade.TapAPIFundData)->Any:
|
||||
def OnRtnFund(self, info: ITapTrade.TapAPIFundData)->None:
|
||||
...
|
||||
def OnRspQryExchange(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIExchangeInfo)->Any:
|
||||
def OnRspQryExchange(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIExchangeInfo)->None:
|
||||
...
|
||||
def OnRspQryCommodity(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPICommodityInfo)->Any:
|
||||
def OnRspQryCommodity(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPICommodityInfo)->None:
|
||||
...
|
||||
def OnRspQryContract(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPITradeContractInfo)->Any:
|
||||
def OnRspQryContract(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPITradeContractInfo)->None:
|
||||
...
|
||||
def OnRtnContract(self, info: ITapTrade.TapAPITradeContractInfo)->Any:
|
||||
def OnRtnContract(self, info: ITapTrade.TapAPITradeContractInfo)->None:
|
||||
...
|
||||
def OnRspOrderAction(self, sessionID: int, errorCode: int, info: ITapTrade.TapAPIOrderActionRsp)->Any:
|
||||
def OnRspOrderAction(self, sessionID: int, errorCode: int, info: ITapTrade.TapAPIOrderActionRsp)->None:
|
||||
...
|
||||
def OnRtnOrder(self, info: ITapTrade.TapAPIOrderInfoNotice)->Any:
|
||||
def OnRtnOrder(self, info: ITapTrade.TapAPIOrderInfoNotice)->None:
|
||||
...
|
||||
def OnRspQryOrder(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIOrderInfo)->Any:
|
||||
def OnRspQryOrder(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIOrderInfo)->None:
|
||||
...
|
||||
def OnRspQryOrderProcess(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIOrderInfo)->Any:
|
||||
def OnRspQryOrderProcess(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIOrderInfo)->None:
|
||||
...
|
||||
def OnRspQryFill(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIFillInfo)->Any:
|
||||
def OnRspQryFill(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIFillInfo)->None:
|
||||
...
|
||||
def OnRtnFill(self, info: ITapTrade.TapAPIFillInfo)->Any:
|
||||
def OnRtnFill(self, info: ITapTrade.TapAPIFillInfo)->None:
|
||||
...
|
||||
def OnRspQryPosition(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIPositionInfo)->Any:
|
||||
def OnRspQryPosition(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIPositionInfo)->None:
|
||||
...
|
||||
def OnRtnPosition(self, info: ITapTrade.TapAPIPositionInfo)->Any:
|
||||
def OnRtnPosition(self, info: ITapTrade.TapAPIPositionInfo)->None:
|
||||
...
|
||||
def OnRspQryPositionSummary(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIPositionSummary)->Any:
|
||||
def OnRspQryPositionSummary(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIPositionSummary)->None:
|
||||
...
|
||||
def OnRtnPositionSummary(self, info: ITapTrade.TapAPIPositionSummary)->Any:
|
||||
def OnRtnPositionSummary(self, info: ITapTrade.TapAPIPositionSummary)->None:
|
||||
...
|
||||
def OnRtnPositionProfit(self, info: ITapTrade.TapAPIPositionProfitNotice)->Any:
|
||||
def OnRtnPositionProfit(self, info: ITapTrade.TapAPIPositionProfitNotice)->None:
|
||||
...
|
||||
def OnRspQryCurrency(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPICurrencyInfo)->Any:
|
||||
def OnRspQryCurrency(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPICurrencyInfo)->None:
|
||||
...
|
||||
def OnRspQryTradeMessage(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPITradeMessage)->Any:
|
||||
def OnRspQryTradeMessage(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPITradeMessage)->None:
|
||||
...
|
||||
def OnRtnTradeMessage(self, info: ITapTrade.TapAPITradeMessage)->Any:
|
||||
def OnRtnTradeMessage(self, info: ITapTrade.TapAPITradeMessage)->None:
|
||||
...
|
||||
def OnRspQryHisOrder(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIHisOrderQryRsp)->Any:
|
||||
def OnRspQryHisOrder(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIHisOrderQryRsp)->None:
|
||||
...
|
||||
def OnRspQryHisOrderProcess(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIHisOrderQryRsp)->Any:
|
||||
def OnRspQryHisOrderProcess(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIHisOrderQryRsp)->None:
|
||||
...
|
||||
def OnRspQryHisMatch(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIHisMatchQryRsp)->Any:
|
||||
def OnRspQryHisMatch(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIHisMatchQryRsp)->None:
|
||||
...
|
||||
def OnRspQryHisPosition(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIHisPositionQryRsp)->Any:
|
||||
def OnRspQryHisPosition(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIHisPositionQryRsp)->None:
|
||||
...
|
||||
def OnRspQryHisDelivery(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIHisDeliveryQryRsp)->Any:
|
||||
def OnRspQryHisDelivery(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIHisDeliveryQryRsp)->None:
|
||||
...
|
||||
def OnRspQryAccountCashAdjust(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIAccountCashAdjustQryRsp)->Any:
|
||||
def OnRspQryAccountCashAdjust(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIAccountCashAdjustQryRsp)->None:
|
||||
...
|
||||
def OnRspQryBill(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIBillQryRsp)->Any:
|
||||
def OnRspQryBill(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIBillQryRsp)->None:
|
||||
...
|
||||
def OnRspQryAccountFeeRent(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIAccountFeeRentQryRsp)->Any:
|
||||
def OnRspQryAccountFeeRent(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIAccountFeeRentQryRsp)->None:
|
||||
...
|
||||
def OnRspQryAccountMarginRent(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIAccountMarginRentQryRsp)->Any:
|
||||
def OnRspQryAccountMarginRent(self, sessionID: int, errorCode: int, isLast: int, info: ITapTrade.TapAPIAccountMarginRentQryRsp)->None:
|
||||
...
|
||||
def OnRspHKMarketOrderInsert(self, sessionID: int, errorCode: int, info: ITapTrade.TapAPIOrderMarketInsertRsp)->Any:
|
||||
def OnRspHKMarketOrderInsert(self, sessionID: int, errorCode: int, info: ITapTrade.TapAPIOrderMarketInsertRsp)->None:
|
||||
...
|
||||
def OnRspHKMarketOrderDelete(self, sessionID: int, errorCode: int, info: ITapTrade.TapAPIOrderMarketInsertRsp)->Any:
|
||||
def OnRspHKMarketOrderDelete(self, sessionID: int, errorCode: int, info: ITapTrade.TapAPIOrderMarketInsertRsp)->None:
|
||||
...
|
||||
def OnHKMarketQuoteNotice(self, info: ITapTrade.TapAPIOrderQuoteMarketNotice)->Any:
|
||||
def OnHKMarketQuoteNotice(self, info: ITapTrade.TapAPIOrderQuoteMarketNotice)->None:
|
||||
...
|
||||
def OnRspOrderLocalRemove(self, sessionID: int, errorCode: int, info: ITapTrade.TapAPIOrderLocalRemoveRsp)->Any:
|
||||
def OnRspOrderLocalRemove(self, sessionID: int, errorCode: int, info: ITapTrade.TapAPIOrderLocalRemoveRsp)->None:
|
||||
...
|
||||
def OnRspOrderLocalInput(self, sessionID: int, errorCode: int, info: ITapTrade.TapAPIOrderInfo)->Any:
|
||||
def OnRspOrderLocalInput(self, sessionID: int, errorCode: int, info: ITapTrade.TapAPIOrderInfo)->None:
|
||||
...
|
||||
def OnRspOrderLocalModify(self, sessionID: int, errorCode: int, info: ITapTrade.TapAPIOrderInfo)->Any:
|
||||
def OnRspOrderLocalModify(self, sessionID: int, errorCode: int, info: ITapTrade.TapAPIOrderInfo)->None:
|
||||
...
|
||||
def OnRspOrderLocalTransfer(self, sessionID: int, errorCode: int, info: ITapTrade.TapAPIOrderInfo)->Any:
|
||||
def OnRspOrderLocalTransfer(self, sessionID: int, errorCode: int, info: ITapTrade.TapAPIOrderInfo)->None:
|
||||
...
|
||||
def OnRspFillLocalInput(self, sessionID: int, errorCode: int, info: ITapTrade.TapAPIFillLocalInputReq)->Any:
|
||||
def OnRspFillLocalInput(self, sessionID: int, errorCode: int, info: ITapTrade.TapAPIFillLocalInputReq)->None:
|
||||
...
|
||||
def OnRspFillLocalRemove(self, sessionID: int, errorCode: int, info: ITapTrade.TapAPIFillLocalRemoveReq)->Any:
|
||||
def OnRspFillLocalRemove(self, sessionID: int, errorCode: int, info: ITapTrade.TapAPIFillLocalRemoveReq)->None:
|
||||
...
|
||||
class ITapTradeAPI():
|
||||
|
||||
|
@ -1,32 +1,55 @@
|
||||
from typing import Any, Sequence, Optional
|
||||
import sys
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
from typing import Any, Dict, Optional, Tuple
|
||||
|
||||
from vnpy.api.itap.vnitap import (
|
||||
CreateTapQuoteAPI,
|
||||
GetITapTradeAPIVersion,
|
||||
GetTapQuoteAPIVersion,
|
||||
ITapQuoteAPINotify,
|
||||
TapAPIApplicationInfo,
|
||||
TapAPIContract,
|
||||
TapAPIQuotLoginRspInfo,
|
||||
TapAPIQuoteCommodityInfo,
|
||||
TapAPIQuoteContractInfo,
|
||||
TapAPIQuoteWhole,
|
||||
TAPIERROR_SUCCEED,
|
||||
TapAPIQuoteLoginAuth,
|
||||
ITapQuoteAPI,
|
||||
APIYNFLAG_NO,
|
||||
FreeTapQuoteAPI,
|
||||
)
|
||||
from vnpy.api.itap.vnitap import (APIYNFLAG_NO, AsyncDispatchException, CreateTapQuoteAPI,
|
||||
FreeTapQuoteAPI, ITapQuoteAPI, ITapQuoteAPINotify,
|
||||
TAPIERROR_SUCCEED, TAPI_CALLPUT_FLAG_NONE,
|
||||
TAPI_COMMODITY_TYPE_FUTURES, TAPI_COMMODITY_TYPE_INDEX,
|
||||
TAPI_COMMODITY_TYPE_OPTION, TAPI_COMMODITY_TYPE_SPOT,
|
||||
TAPI_COMMODITY_TYPE_STOCK, TapAPIApplicationInfo, TapAPIContract,
|
||||
TapAPIQuotLoginRspInfo, TapAPIQuoteCommodityInfo,
|
||||
TapAPIQuoteContractInfo, TapAPIQuoteLoginAuth, TapAPIQuoteWhole,
|
||||
set_async_callback_exception_handler)
|
||||
|
||||
from vnpy.api.itap.error_codes import error_map
|
||||
from vnpy.event import EventEngine
|
||||
from vnpy.trader.constant import Exchange, Product
|
||||
from vnpy.trader.gateway import BaseGateway
|
||||
from vnpy.trader.object import (
|
||||
CancelRequest,
|
||||
HistoryRequest,
|
||||
ContractData,
|
||||
OrderRequest,
|
||||
SubscribeRequest,
|
||||
)
|
||||
from vnpy.api.itap.error_codes import error_map
|
||||
TickData)
|
||||
|
||||
PRODUCT_TYPE_ITAP2VT = {
|
||||
TAPI_COMMODITY_TYPE_SPOT: Product.SPOT,
|
||||
TAPI_COMMODITY_TYPE_FUTURES: Product.FUTURES,
|
||||
TAPI_COMMODITY_TYPE_OPTION: Product.OPTION,
|
||||
TAPI_COMMODITY_TYPE_INDEX: Product.INDEX,
|
||||
TAPI_COMMODITY_TYPE_STOCK: Product.EQUITY,
|
||||
}
|
||||
|
||||
EXCHANGE_ITAP2VT = {
|
||||
'SGX': Exchange.SGX,
|
||||
'INE': Exchange.INE,
|
||||
'APEX': Exchange.APEX,
|
||||
'NYMEX': Exchange.NYMEX,
|
||||
'LME': Exchange.LME,
|
||||
'COMEX': Exchange.COMEX, # verify: I added this exchange in vnpy, is this correct?
|
||||
'CBOT': Exchange.CBOT,
|
||||
'HKEX': Exchange.HKFE, # verify: is this correct?,
|
||||
'CME': Exchange.CME,
|
||||
}
|
||||
EXCHANGE_VT2ITAP = {v: k for k, v in EXCHANGE_ITAP2VT.items()}
|
||||
|
||||
|
||||
def parse_datetime(dt_str: str):
|
||||
# todo: 我不知道这个时间所用的是哪种时间
|
||||
# yyyy-MM-dd hh:nn:ss.xxx
|
||||
return datetime.strptime(dt_str, "%Y-%m-%d %H:%M:%S.%f")
|
||||
|
||||
|
||||
def error_to_str(err_code: int) -> str:
|
||||
@ -36,15 +59,37 @@ def error_to_str(err_code: int) -> str:
|
||||
return f"Unknown error({err_code})"
|
||||
|
||||
|
||||
@dataclass()
|
||||
class ContractExtraInfo:
|
||||
"""
|
||||
缓存一些ITAP API不直接提供的信息,而且仅仅保存这些信息。Symbol之类的作为键就不保存在这里面了
|
||||
"""
|
||||
name: str
|
||||
commodity_type: int
|
||||
commodity_no: str
|
||||
|
||||
|
||||
class QuoteNotify(ITapQuoteAPINotify):
|
||||
|
||||
def __init__(self, gateway: "ITapGateway"):
|
||||
super().__init__()
|
||||
self.gateway = gateway
|
||||
|
||||
@property
|
||||
def api(self) -> ITapQuoteAPI:
|
||||
return self.gateway.api
|
||||
|
||||
def OnRspLogin(self, errorCode: int, info: TapAPIQuotLoginRspInfo) -> Any:
|
||||
if TAPIERROR_SUCCEED == errorCode:
|
||||
print("[+] login succeed!")
|
||||
else:
|
||||
print(f"[-] login failed! {error_to_str(errorCode)}")
|
||||
if self.gateway.if_error_write_log(errorCode, "OnRspQryCommodity"):
|
||||
self.gateway.write_log("行情服务器登录失败")
|
||||
return
|
||||
self.gateway.write_log("行情服务器登录成功")
|
||||
|
||||
def OnAPIReady(self) -> Any:
|
||||
print("OnApiReady")
|
||||
error_code, sessionId = self.api.QryCommodity()
|
||||
if self.gateway.if_error_write_log(error_code, "api.QryCommodity"):
|
||||
return
|
||||
|
||||
def OnDisconnect(self, reasonCode: int) -> Any:
|
||||
print(f"OnDisconnect : {error_to_str(reasonCode)}")
|
||||
@ -56,25 +101,96 @@ class QuoteNotify(ITapQuoteAPINotify):
|
||||
isLast: int,
|
||||
info: TapAPIQuoteCommodityInfo,
|
||||
) -> Any:
|
||||
print(f"OnRspQryCommodity : {error_to_str(errorCode)}")
|
||||
if self.gateway.if_error_write_log(errorCode, "OnRspQryCommodity"):
|
||||
return
|
||||
|
||||
error_code, session_id = self.api.QryContract(info.Commodity)
|
||||
if self.gateway.if_error_write_log(error_code, "api.QryContract"):
|
||||
return
|
||||
|
||||
def OnRspQryContract(
|
||||
self, sessionID: int, errorCode: int, isLast: int, info: TapAPIQuoteContractInfo
|
||||
) -> Any:
|
||||
print("OnRspQryContract")
|
||||
if self.gateway.if_error_write_log(errorCode, "OnRspQryContract"):
|
||||
return
|
||||
if info is not None: # isLast == True ==> info is None
|
||||
symbol = info.Contract.ContractNo1 # what's the different between No1 and No2?
|
||||
exchange = EXCHANGE_ITAP2VT[info.Contract.Commodity.ExchangeNo]
|
||||
name = info.ContractName
|
||||
contract_data = ContractData(
|
||||
gateway_name=self.gateway.gateway_name,
|
||||
symbol=symbol,
|
||||
exchange=exchange,
|
||||
name=name,
|
||||
product=PRODUCT_TYPE_ITAP2VT.get(info.ContractType, Product.EQUITY),
|
||||
size=1, # verify: no key for this
|
||||
pricetick=1, # verify: no key for this
|
||||
min_volume=1, # verify: no key for this
|
||||
# ...
|
||||
)
|
||||
contract_extra_info = ContractExtraInfo(
|
||||
name=name,
|
||||
commodity_type=info.Contract.Commodity.CommodityType,
|
||||
commodity_no=info.Contract.Commodity.CommodityNo,
|
||||
)
|
||||
self.gateway.contract_extra_infos[(symbol, exchange)] = contract_extra_info
|
||||
self.gateway.on_contract(contract_data)
|
||||
|
||||
def OnRspSubscribeQuote(
|
||||
self, sessionID: int, errorCode: int, isLast: int, info: TapAPIQuoteWhole
|
||||
) -> Any:
|
||||
print("OnRspSubscribeQuote")
|
||||
if self.gateway.if_error_write_log(errorCode, "OnRspSubscribeQuote"):
|
||||
return
|
||||
|
||||
def OnRspUnSubscribeQuote(
|
||||
self, sessionID: int, errorCode: int, isLast: int, info: TapAPIContract
|
||||
) -> Any:
|
||||
print("OnRspUnSubscribeQuote")
|
||||
if self.gateway.if_error_write_log(errorCode, "OnRspUnSubscribeQuote"):
|
||||
return
|
||||
|
||||
def OnRtnQuote(self, info: TapAPIQuoteWhole) -> Any:
|
||||
print("OnRtnQuote")
|
||||
symbol = info.Contract.ContractNo1
|
||||
exchange = EXCHANGE_ITAP2VT[info.Contract.Commodity.ExchangeNo]
|
||||
extra_info = self.gateway.contract_extra_infos[(symbol, exchange)]
|
||||
tick = TickData(
|
||||
gateway_name=self.gateway.gateway_name,
|
||||
symbol=symbol,
|
||||
exchange=exchange,
|
||||
datetime=parse_datetime(info.DateTimeStamp),
|
||||
name=extra_info.name,
|
||||
volume=info.QTotalQty,
|
||||
last_price=info.QLastPrice,
|
||||
last_volume=info.QLastQty,
|
||||
limit_up=info.QLimitUpPrice,
|
||||
limit_down=info.QLimitDownPrice,
|
||||
open_price=info.QOpeningPrice,
|
||||
high_price=info.QHighPrice,
|
||||
low_price=info.QLowPrice,
|
||||
pre_close=info.QPreClosingPrice,
|
||||
bid_price_1=info.QBidPrice[0],
|
||||
bid_price_2=info.QBidPrice[1],
|
||||
bid_price_3=info.QBidPrice[3],
|
||||
bid_price_4=info.QBidPrice[4],
|
||||
bid_price_5=info.QBidPrice[5],
|
||||
ask_price_1=info.QAskPrice[0],
|
||||
ask_price_2=info.QAskPrice[1],
|
||||
ask_price_3=info.QAskPrice[2],
|
||||
ask_price_4=info.QAskPrice[3],
|
||||
ask_price_5=info.QAskPrice[4],
|
||||
bid_volume_1=info.QBidQty[0],
|
||||
bid_volume_2=info.QBidQty[1],
|
||||
bid_volume_3=info.QBidQty[2],
|
||||
bid_volume_4=info.QBidQty[3],
|
||||
bid_volume_5=info.QBidQty[4],
|
||||
ask_volume_1=info.QAskQty[0],
|
||||
ask_volume_2=info.QAskQty[1],
|
||||
ask_volume_3=info.QAskQty[2],
|
||||
ask_volume_4=info.QAskQty[3],
|
||||
ask_volume_5=info.QAskQty[4],
|
||||
)
|
||||
self.gateway.on_tick(tick=tick)
|
||||
|
||||
|
||||
class ITapGateway(BaseGateway):
|
||||
@ -85,11 +201,16 @@ class ITapGateway(BaseGateway):
|
||||
"quote_username": "",
|
||||
"quote_password": "",
|
||||
}
|
||||
exchanges = list(EXCHANGE_VT2ITAP.keys())
|
||||
|
||||
def __init__(self, event_engine: EventEngine):
|
||||
super().__init__(event_engine, "ITAP")
|
||||
self.api: Optional[ITapQuoteAPI] = None
|
||||
self.quote_notify = QuoteNotify()
|
||||
self.quote_notify = QuoteNotify(self)
|
||||
|
||||
# [symbol, exchange] : [CommodityType, CommodityNo]
|
||||
self.contract_extra_infos: Dict[Tuple[str, Exchange], ContractExtraInfo] = {}
|
||||
set_async_callback_exception_handler(self._async_callback_exception_handler)
|
||||
|
||||
def connect(self, setting: dict):
|
||||
auth_code = setting["auth_code"]
|
||||
@ -97,24 +218,25 @@ class ITapGateway(BaseGateway):
|
||||
quote_port = setting["quote_port"]
|
||||
quote_username = setting["quote_username"]
|
||||
quote_password = setting["quote_password"]
|
||||
print("quote version:", GetTapQuoteAPIVersion())
|
||||
print("trade version:", GetITapTradeAPIVersion())
|
||||
# print("quote version:", GetTapQuoteAPIVersion())
|
||||
# print("trade version:", GetITapTradeAPIVersion())
|
||||
|
||||
ai = TapAPIApplicationInfo()
|
||||
ai.AuthCode = auth_code
|
||||
|
||||
# iResult是输出参数,Python中只能用返回值作为输出。
|
||||
# 具体输出了哪些,看pyi的注释
|
||||
# 具体输出了哪些,可以看pyi的注释
|
||||
api, iResult = CreateTapQuoteAPI(ai)
|
||||
if api is None:
|
||||
error_code = iResult # 看API文档的注释:iResult就是错误代码
|
||||
print(f"CreateTapQuoteAPI error: {error_to_str(error_code)}")
|
||||
return # todo: error report
|
||||
self.if_error_write_log(iResult, "CreateTapQuoteAPI")
|
||||
return
|
||||
|
||||
assert self.api is None
|
||||
self.api = api
|
||||
|
||||
api.SetAPINotify(self.quote_notify)
|
||||
error_code: int = api.SetHostAddress(quote_host, quote_port)
|
||||
if TAPIERROR_SUCCEED != error_code:
|
||||
print(f"SetHostAddress error: {error_to_str(error_code)}")
|
||||
if self.if_error_write_log(error_code, "SetHostAddress"):
|
||||
return
|
||||
|
||||
# login
|
||||
@ -124,10 +246,8 @@ class ITapGateway(BaseGateway):
|
||||
la.ISDDA = APIYNFLAG_NO
|
||||
la.ISModifyPassword = APIYNFLAG_NO
|
||||
error_code: int = api.Login(la) # async
|
||||
if TAPIERROR_SUCCEED != error_code:
|
||||
print(f"Login error: {error_to_str(error_code)}")
|
||||
if self.if_error_write_log(error_code, "api.Login"):
|
||||
return
|
||||
self.api = api
|
||||
|
||||
def close(self):
|
||||
self.api.SetAPINotify(None)
|
||||
@ -137,7 +257,17 @@ class ITapGateway(BaseGateway):
|
||||
pass
|
||||
|
||||
def subscribe(self, req: SubscribeRequest):
|
||||
pass
|
||||
contract = TapAPIContract()
|
||||
extra_info = self.contract_extra_infos[(req.symbol, req.exchange)]
|
||||
contract.Commodity.ExchangeNo = EXCHANGE_VT2ITAP[req.exchange]
|
||||
contract.Commodity.CommodityType = extra_info.commodity_type
|
||||
contract.Commodity.CommodityNo = extra_info.commodity_no
|
||||
contract.ContractNo1 = req.symbol
|
||||
contract.CallOrPutFlag1 = TAPI_CALLPUT_FLAG_NONE
|
||||
contract.CallOrPutFlag2 = TAPI_CALLPUT_FLAG_NONE
|
||||
error_code, session_id = self.api.SubscribeQuote(contract)
|
||||
if self.if_error_write_log(error_code, "api.SubscribeQuote"):
|
||||
return
|
||||
|
||||
def send_order(self, req: OrderRequest) -> str:
|
||||
pass
|
||||
@ -150,3 +280,22 @@ class ITapGateway(BaseGateway):
|
||||
|
||||
def query_position(self):
|
||||
pass
|
||||
|
||||
def _async_callback_exception_handler(self, e: AsyncDispatchException):
|
||||
error_str = (f"发生内部错误,位置:\n{e.instance}.{e.function_name},详细信息:\n"
|
||||
f"{e.what}\n"
|
||||
)
|
||||
print(error_str, file=sys.stderr, flush=True)
|
||||
self.write_log(error_str)
|
||||
return True
|
||||
|
||||
def if_error_write_log(self, error_code: int, function: str):
|
||||
"""
|
||||
检查返回值,如果发生错误,调用write_log报告该错误,并返回True
|
||||
:return: 若有错误发生,返回True
|
||||
"""
|
||||
if TAPIERROR_SUCCEED != error_code:
|
||||
error_msg = f"调用{function}时出错:\n{error_to_str(error_code)}"
|
||||
self.write_log(error_msg)
|
||||
print(error_msg, file=sys.stderr)
|
||||
return True
|
||||
|
Loading…
Reference in New Issue
Block a user