[Add] 捕获xtp回调函数内部发生的错误
[Mod] 使用autocxxpy0.2.1来封装xtp
This commit is contained in:
parent
72dd05dcb5
commit
a2b55dda02
Binary file not shown.
@ -7,19 +7,34 @@ if typing.TYPE_CHECKING:
|
||||
from .vnxtp import *
|
||||
|
||||
|
||||
def set_async_callback_exception_handler(handler: Callable[[AsyncDispatchException], None]):
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
class AsyncDispatchException:
|
||||
what: str
|
||||
instance: object
|
||||
function_name: str
|
||||
|
||||
|
||||
from . import vnxtp_XTP as XTP
|
||||
class XTPRspInfoStruct():
|
||||
|
||||
|
||||
error_id: int
|
||||
error_msg: Sequence[int]
|
||||
error_msg: str
|
||||
|
||||
|
||||
class XTPSpecificTickerStruct():
|
||||
|
||||
|
||||
exchange_id: XTP_EXCHANGE_TYPE
|
||||
ticker: Sequence[int]
|
||||
ticker: str
|
||||
|
||||
|
||||
class XTPMarketDataStockExData():
|
||||
@ -71,7 +86,7 @@ class XTPMarketDataStruct():
|
||||
|
||||
|
||||
exchange_id: XTP_EXCHANGE_TYPE
|
||||
ticker: Sequence[int]
|
||||
ticker: str
|
||||
last_price: float
|
||||
pre_close_price: float
|
||||
open_price: float
|
||||
@ -95,7 +110,7 @@ class XTPMarketDataStruct():
|
||||
bid_qty: Sequence[int]
|
||||
ask_qty: Sequence[int]
|
||||
trades_count: int
|
||||
ticker_status: Sequence[int]
|
||||
ticker_status: str
|
||||
stk: XTPMarketDataStockExData
|
||||
opt: XTPMarketDataOptionExData
|
||||
data_type: XTP_MARKETDATA_TYPE
|
||||
@ -106,8 +121,8 @@ class XTPQuoteStaticInfo():
|
||||
|
||||
|
||||
exchange_id: XTP_EXCHANGE_TYPE
|
||||
ticker: Sequence[int]
|
||||
ticker_name: Sequence[int]
|
||||
ticker: str
|
||||
ticker_name: str
|
||||
ticker_type: XTP_TICKER_TYPE
|
||||
pre_close_price: float
|
||||
upper_limit_price: float
|
||||
@ -121,7 +136,7 @@ class OrderBookStruct():
|
||||
|
||||
|
||||
exchange_id: XTP_EXCHANGE_TYPE
|
||||
ticker: Sequence[int]
|
||||
ticker: str
|
||||
last_price: float
|
||||
qty: int
|
||||
turnover: float
|
||||
@ -161,7 +176,7 @@ class XTPTickByTickStruct():
|
||||
|
||||
|
||||
exchange_id: XTP_EXCHANGE_TYPE
|
||||
ticker: Sequence[int]
|
||||
ticker: str
|
||||
seq: int
|
||||
data_time: int
|
||||
type: XTP_TBT_TYPE
|
||||
@ -173,7 +188,7 @@ class XTPTickerPriceInfo():
|
||||
|
||||
|
||||
exchange_id: XTP_EXCHANGE_TYPE
|
||||
ticker: Sequence[int]
|
||||
ticker: str
|
||||
last_price: float
|
||||
|
||||
|
||||
@ -182,7 +197,7 @@ class XTPOrderInsertInfo():
|
||||
|
||||
order_xtp_id: int
|
||||
order_client_id: int
|
||||
ticker: Sequence[int]
|
||||
ticker: str
|
||||
market: XTP_MARKET_TYPE
|
||||
price: float
|
||||
stop_price: float
|
||||
@ -210,7 +225,7 @@ class XTPOrderInfo():
|
||||
order_client_id: int
|
||||
order_cancel_client_id: int
|
||||
order_cancel_xtp_id: int
|
||||
ticker: Sequence[int]
|
||||
ticker: str
|
||||
market: XTP_MARKET_TYPE
|
||||
price: float
|
||||
quantity: int
|
||||
@ -227,7 +242,7 @@ class XTPOrderInfo():
|
||||
update_time: int
|
||||
cancel_time: int
|
||||
trade_amount: float
|
||||
order_local_id: Sequence[int]
|
||||
order_local_id: str
|
||||
order_status: XTP_ORDER_STATUS_TYPE
|
||||
order_submit_status: XTP_ORDER_SUBMIT_STATUS_TYPE
|
||||
order_type: int
|
||||
@ -238,16 +253,16 @@ class XTPTradeReport():
|
||||
|
||||
order_xtp_id: int
|
||||
order_client_id: int
|
||||
ticker: Sequence[int]
|
||||
ticker: str
|
||||
market: XTP_MARKET_TYPE
|
||||
local_order_id: int
|
||||
exec_id: Sequence[int]
|
||||
exec_id: str
|
||||
price: float
|
||||
quantity: int
|
||||
trade_time: int
|
||||
trade_amount: float
|
||||
report_index: int
|
||||
order_exch_id: Sequence[int]
|
||||
order_exch_id: str
|
||||
trade_type: int
|
||||
u32: int
|
||||
side: int
|
||||
@ -255,13 +270,13 @@ class XTPTradeReport():
|
||||
reserved1: int
|
||||
reserved2: int
|
||||
business_type: XTP_BUSINESS_TYPE
|
||||
branch_pbu: Sequence[int]
|
||||
branch_pbu: str
|
||||
|
||||
|
||||
class XTPQueryOrderReq():
|
||||
|
||||
|
||||
ticker: Sequence[int]
|
||||
ticker: str
|
||||
begin_time: int
|
||||
end_time: int
|
||||
|
||||
@ -270,13 +285,13 @@ class XTPQueryReportByExecIdReq():
|
||||
|
||||
|
||||
order_xtp_id: int
|
||||
exec_id: Sequence[int]
|
||||
exec_id: str
|
||||
|
||||
|
||||
class XTPQueryTraderReq():
|
||||
|
||||
|
||||
ticker: Sequence[int]
|
||||
ticker: str
|
||||
begin_time: int
|
||||
end_time: int
|
||||
|
||||
@ -311,8 +326,8 @@ class XTPQueryAssetRsp():
|
||||
class XTPQueryStkPositionRsp():
|
||||
|
||||
|
||||
ticker: Sequence[int]
|
||||
ticker_name: Sequence[int]
|
||||
ticker: str
|
||||
ticker_name: str
|
||||
market: XTP_MARKET_TYPE
|
||||
total_qty: int
|
||||
sellable_qty: int
|
||||
@ -350,17 +365,17 @@ class XTPQueryStructuredFundInfoReq():
|
||||
|
||||
|
||||
exchange_id: XTP_EXCHANGE_TYPE
|
||||
sf_ticker: Sequence[int]
|
||||
sf_ticker: str
|
||||
|
||||
|
||||
class XTPStructuredFundInfo():
|
||||
|
||||
|
||||
exchange_id: XTP_EXCHANGE_TYPE
|
||||
sf_ticker: Sequence[int]
|
||||
sf_ticker_name: Sequence[int]
|
||||
ticker: Sequence[int]
|
||||
ticker_name: Sequence[int]
|
||||
sf_ticker: str
|
||||
sf_ticker_name: str
|
||||
ticker: str
|
||||
ticker_name: str
|
||||
split_merge_status: XTP_SPLIT_MERGE_STATUS
|
||||
ratio: int
|
||||
min_split_qty: int
|
||||
@ -372,15 +387,15 @@ class XTPQueryETFBaseReq():
|
||||
|
||||
|
||||
market: XTP_MARKET_TYPE
|
||||
ticker: Sequence[int]
|
||||
ticker: str
|
||||
|
||||
|
||||
class XTPQueryETFBaseRsp():
|
||||
|
||||
|
||||
market: XTP_MARKET_TYPE
|
||||
etf: Sequence[int]
|
||||
subscribe_redemption_ticker: Sequence[int]
|
||||
etf: str
|
||||
subscribe_redemption_ticker: str
|
||||
unit: int
|
||||
subscribe_status: int
|
||||
redemption_status: int
|
||||
@ -395,16 +410,16 @@ class XTPQueryETFComponentReq():
|
||||
|
||||
|
||||
market: XTP_MARKET_TYPE
|
||||
ticker: Sequence[int]
|
||||
ticker: str
|
||||
|
||||
|
||||
class XTPQueryETFComponentRsp():
|
||||
|
||||
|
||||
market: XTP_MARKET_TYPE
|
||||
ticker: Sequence[int]
|
||||
component_ticker: Sequence[int]
|
||||
component_name: Sequence[int]
|
||||
ticker: str
|
||||
component_ticker: str
|
||||
component_name: str
|
||||
quantity: int
|
||||
component_market: XTP_MARKET_TYPE
|
||||
replace_type: ETF_REPLACE_TYPE
|
||||
@ -416,8 +431,8 @@ class XTPQueryIPOTickerRsp():
|
||||
|
||||
|
||||
market: XTP_MARKET_TYPE
|
||||
ticker: Sequence[int]
|
||||
ticker_name: Sequence[int]
|
||||
ticker: str
|
||||
ticker_name: str
|
||||
price: float
|
||||
unit: int
|
||||
qty_upper_limit: int
|
||||
@ -434,17 +449,17 @@ class XTPQueryOptionAuctionInfoReq():
|
||||
|
||||
|
||||
market: XTP_MARKET_TYPE
|
||||
ticker: Sequence[int]
|
||||
ticker: str
|
||||
|
||||
|
||||
class XTPQueryOptionAuctionInfoRsp():
|
||||
|
||||
|
||||
ticker: Sequence[int]
|
||||
ticker: str
|
||||
security_id_source: XTP_MARKET_TYPE
|
||||
symbol: Sequence[int]
|
||||
contract_id: Sequence[int]
|
||||
underlying_security_id: Sequence[int]
|
||||
symbol: str
|
||||
contract_id: str
|
||||
underlying_security_id: str
|
||||
underlying_security_id_source: XTP_MARKET_TYPE
|
||||
list_date: int
|
||||
last_trade_date: int
|
||||
@ -483,8 +498,8 @@ class XTPFundTransferReq():
|
||||
|
||||
|
||||
serial_id: int
|
||||
fund_account: Sequence[int]
|
||||
password: Sequence[int]
|
||||
fund_account: str
|
||||
password: str
|
||||
amount: float
|
||||
transfer_type: XTP_FUND_TRANSFER_TYPE
|
||||
|
||||
@ -610,7 +625,7 @@ class XTP_POSITION_DIRECTION_TYPE(Enum):
|
||||
class XTP_MARKETDATA_TYPE(Enum):
|
||||
XTP_MARKETDATA_ACTUAL: XTP_MARKETDATA_TYPE
|
||||
XTP_MARKETDATA_OPTION: XTP_MARKETDATA_TYPE
|
||||
XTPVersionType = Sequence[int]
|
||||
XTPVersionType = str
|
||||
XTP_LOG_LEVEL = XTP_LOG_LEVEL
|
||||
XTP_PROTOCOL_TYPE = XTP_PROTOCOL_TYPE
|
||||
XTP_EXCHANGE_TYPE = XTP_EXCHANGE_TYPE
|
||||
|
@ -277,9 +277,14 @@ void generate_class_XTP_API_QuoteApi(pybind11::object & parent)
|
||||
PyQuoteApi
|
||||
> c(parent, "QuoteApi");
|
||||
c.def_static("CreateQuoteApi",
|
||||
autocxxpy::apply_function_transform<
|
||||
autocxxpy::function_constant<
|
||||
&XTP::API::QuoteApi::CreateQuoteApi
|
||||
//,
|
||||
//pybind11::call_guard<pybind11::gil_scoped_release>()
|
||||
>,
|
||||
brigand::list<
|
||||
>
|
||||
>::value,
|
||||
pybind11::call_guard<pybind11::gil_scoped_release>()
|
||||
);
|
||||
c.def("Release",
|
||||
autocxxpy::apply_function_transform<
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/functional.h>
|
||||
#include <autocxxpy/autocxxpy.hpp>
|
||||
|
||||
#include "module.hpp"
|
||||
@ -20,6 +21,12 @@ void additional_init(pybind11::module &m)
|
||||
|
||||
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_readonly("instance", &autocxxpy::async_dispatch_exception::instance);
|
||||
c.def_readonly("function_name", &autocxxpy::async_dispatch_exception::function_name);
|
||||
|
||||
autocxxpy::dispatcher::instance().start();
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <optional>
|
||||
|
||||
#include "brigand.hpp"
|
||||
|
||||
@ -66,7 +67,7 @@ namespace autocxxpy
|
||||
template <auto method>
|
||||
constexpr callback_type callback_type_of_v = callback_type_of<method>::value;
|
||||
|
||||
#ifdef PYBIND11_OVERLOAD_NAME
|
||||
#ifdef AUTOCXXPY_INCLUDED_PYBIND11
|
||||
template <class ret_type>
|
||||
struct pybind11_static_caster {
|
||||
static pybind11::detail::overload_caster_t<ret_type> caster;
|
||||
@ -75,18 +76,59 @@ namespace autocxxpy
|
||||
template <class ret_type>
|
||||
AUTOCXXPY_SELECT_ANY pybind11::detail::overload_caster_t<ret_type> pybind11_static_caster<ret_type>::caster;
|
||||
|
||||
struct async_dispatch_exception : public std::exception
|
||||
{
|
||||
async_dispatch_exception(const char *what, const pybind11::object &instance, std::string function_name)
|
||||
: std::exception(what), instance(instance), function_name(function_name)
|
||||
{}
|
||||
pybind11::object instance;
|
||||
std::string function_name;
|
||||
inline const char* what() noexcept
|
||||
{
|
||||
return std::exception::what();
|
||||
}
|
||||
};
|
||||
|
||||
struct async_callback_exception_handler
|
||||
{
|
||||
using handler_type = std::function<void(const async_dispatch_exception&)>;
|
||||
static handler_type custom_handler;
|
||||
|
||||
inline static void handle_excepiton(const async_dispatch_exception&e)
|
||||
{
|
||||
if (custom_handler)
|
||||
{
|
||||
custom_handler(e);
|
||||
}
|
||||
}
|
||||
|
||||
inline static void set_handler(const handler_type& handler)
|
||||
{
|
||||
custom_handler = handler;
|
||||
}
|
||||
};
|
||||
|
||||
AUTOCXXPY_SELECT_ANY async_callback_exception_handler::handler_type async_callback_exception_handler::custom_handler;
|
||||
#endif
|
||||
|
||||
namespace arg_helper
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// stores
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// # todo: char8, char16, char32, wchar_t, etc...
|
||||
// # todo: shall i copy only const type, treating non-const type as output pointer?
|
||||
inline auto save(const char *val)
|
||||
inline std::optional<std::string> save(const char* val)
|
||||
{ // match const char *
|
||||
if (nullptr == val) AUTOCXXPY_UNLIKELY
|
||||
return std::nullopt; // maybe empty string is also a choice?
|
||||
return std::string(val);
|
||||
}
|
||||
inline auto save(char *val)
|
||||
inline std::optional<std::string> save(char* val)
|
||||
{ // match char *
|
||||
if (nullptr == val) AUTOCXXPY_UNLIKELY
|
||||
return std::nullopt; // maybe empty string is also a choice?
|
||||
return std::string(val);
|
||||
}
|
||||
template<size_t size>
|
||||
@ -101,29 +143,41 @@ namespace autocxxpy
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T &save(T *val)
|
||||
inline std::optional<T> save(T * val)
|
||||
{ // match pointer
|
||||
if (nullptr == val) AUTOCXXPY_UNLIKELY
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
return *val;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T &save(const T *val)
|
||||
inline std::optional<T>& save(const T * val)
|
||||
{ // match const pointer
|
||||
if (nullptr == val) AUTOCXXPY_UNLIKELY
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
return const_cast<T&>(*val);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T &save(const T &val)
|
||||
inline T& save(const T & val)
|
||||
{ // match everything else : just use original type
|
||||
return const_cast<T&>(val);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// loads
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class to_type>
|
||||
struct loader
|
||||
{ // match default(everyting besides pointer)
|
||||
template <class src_type>
|
||||
inline to_type operator ()(src_type &val)
|
||||
inline to_type operator ()(src_type& val)
|
||||
{
|
||||
return val;
|
||||
}
|
||||
@ -132,57 +186,57 @@ namespace autocxxpy
|
||||
template <size_t size>
|
||||
struct loader<const string_array<size>>
|
||||
{ // match const char []
|
||||
using to_type = const char *;
|
||||
inline to_type operator ()(const std::string &val)
|
||||
using to_type = const char*;
|
||||
inline to_type operator ()(const std::string& val)
|
||||
{
|
||||
return const_cast<char *>(val.data());
|
||||
return const_cast<char*>(val.data());
|
||||
}
|
||||
};
|
||||
|
||||
template <size_t size>
|
||||
struct loader<string_array<size>>
|
||||
{ // match char []
|
||||
using to_type = char *;
|
||||
inline to_type operator ()(const std::string &val)
|
||||
using to_type = char*;
|
||||
inline to_type operator ()(const std::string& val)
|
||||
{
|
||||
return const_cast<char *>(val.data());
|
||||
return const_cast<char*>(val.data());
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct loader<const char *>
|
||||
struct loader<const char*>
|
||||
{ // match const char *
|
||||
using to_type = const char *;
|
||||
inline to_type operator ()(const std::string &val)
|
||||
using to_type = const char*;
|
||||
inline to_type operator ()(const std::optional<std::string>& val)
|
||||
{
|
||||
return const_cast<char *>(val.data());
|
||||
if (val) AUTOCXXPY_LIKELY
|
||||
return const_cast<char*>(val->data());
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct loader<char *>
|
||||
struct loader<char*>
|
||||
{ // match char *
|
||||
using to_type = char *;
|
||||
inline to_type operator ()(const std::string &val)
|
||||
using to_type = char*;
|
||||
inline to_type operator ()(const std::optional<std::string>& val)
|
||||
{
|
||||
return const_cast<char *>(val.data());
|
||||
if (val) AUTOCXXPY_LIKELY
|
||||
return const_cast<char*>(val->data());
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
template <class to_type>
|
||||
struct loader<to_type *>
|
||||
struct loader<to_type*>
|
||||
{ // match pointer
|
||||
template <class src_type>
|
||||
inline to_type *operator ()(src_type &val)
|
||||
inline to_type* operator ()(const std::optional<src_type>& val)
|
||||
{ // val to poiner
|
||||
return const_cast<to_type *>(&val);
|
||||
if (val) AUTOCXXPY_LIKELY
|
||||
return const_cast<to_type*>(&(*val));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//template <class src_type>
|
||||
//inline to_type *operator ()(src_type *val)
|
||||
//{ // pointer to pointer
|
||||
// return val;
|
||||
//}
|
||||
};
|
||||
|
||||
};
|
||||
@ -195,7 +249,7 @@ namespace autocxxpy
|
||||
using class_type = class_of_member_method_t<method>;
|
||||
public:
|
||||
template <class ... arg_types>
|
||||
inline static ret_type call(class_type *instance, const char *py_func_name, arg_types ... args)
|
||||
inline static ret_type call(class_type* instance, const char* py_func_name, arg_types ... args)
|
||||
{
|
||||
if constexpr (callback_type_of_v<method> == callback_type::Direct)
|
||||
{
|
||||
@ -211,47 +265,70 @@ namespace autocxxpy
|
||||
}
|
||||
|
||||
template <class ... arg_types>
|
||||
inline static void async(class_type *instance, const char *py_func_name, arg_types ... args)
|
||||
inline static void async(class_type* instance, const char* py_func_name, arg_types ... args)
|
||||
{
|
||||
return async_impl(instance, py_func_name, std::index_sequence_for<arg_types ...>{}, args ...);
|
||||
}
|
||||
|
||||
template <class ... arg_types>
|
||||
inline static ret_type sync(class_type *instance, const char * py_func_name, arg_types ... args)
|
||||
inline static ret_type sync(class_type * instance, const char* py_func_name, arg_types ... args)
|
||||
{
|
||||
// if this code is under test environment, we don't need pybind11
|
||||
// since header of pybind11 use #pragma once, no macros is defined, we use a public macro to check if pybind11 is included or not
|
||||
#ifdef PYBIND11_OVERLOAD_NAME
|
||||
pybind11::gil_scoped_acquire gil;
|
||||
pybind11::function overload = pybind11::get_overload(static_cast<const class_type *>(instance), py_func_name);
|
||||
if (overload) {
|
||||
auto o = overload(args ...);
|
||||
if (pybind11::detail::cast_is_temporary_value_reference<ret_type>::value) {
|
||||
auto & caster = pybind11_static_caster<ret_type>::caster;
|
||||
return pybind11::detail::cast_ref<ret_type>(std::move(o), caster);
|
||||
pybind11::function overload = pybind11::get_overload(static_cast<const class_type*>(instance), py_func_name);
|
||||
if (overload) AUTOCXXPY_LIKELY{
|
||||
try
|
||||
{
|
||||
auto result = overload(args ...);
|
||||
if (pybind11::detail::cast_is_temporary_value_reference<ret_type>::value)
|
||||
{
|
||||
auto& caster = pybind11_static_caster<ret_type>::caster;
|
||||
return pybind11::detail::cast_ref<ret_type>(std::move(result), caster);
|
||||
}
|
||||
else
|
||||
{
|
||||
return pybind11::detail::cast_safe<ret_type>(std::move(result));
|
||||
}
|
||||
}
|
||||
catch (const pybind11::error_already_set & e)
|
||||
{
|
||||
// todo: option to not to throw when sync is called directly
|
||||
throw async_dispatch_exception(e.what(), pybind11::cast(instance), py_func_name);
|
||||
}
|
||||
else return pybind11::detail::cast_safe<ret_type>(std::move(o));
|
||||
}
|
||||
#endif
|
||||
return (instance->*method)(args ...);
|
||||
}
|
||||
private:
|
||||
template <class ... arg_types, size_t ... idx>
|
||||
inline static void async_impl(class_type *instance, const char *py_func_name, std::index_sequence<idx ...>, arg_types ... args)
|
||||
inline static void async_impl(class_type * instance, const char* py_func_name, std::index_sequence<idx ...>, arg_types ... args)
|
||||
{
|
||||
// wrap for ctp like function calls:
|
||||
// all the pointer might be unavailable after this call, so copy its value into a tuple
|
||||
auto arg_tuple = std::make_tuple(arg_helper::save(args) ...);
|
||||
auto task = [instance, py_func_name, arg_tuple = std::move(arg_tuple)]()
|
||||
{
|
||||
// resolve all value:
|
||||
// if it was originally a pointer, then use pointer type.
|
||||
// if it was originally a value, just keep a reference to that value.
|
||||
sync<arg_types ...>(
|
||||
instance, py_func_name,
|
||||
arg_helper::loader<brigand::at<brigand::list<arg_types ...>, brigand::integral_constant<int, idx> > >{}
|
||||
(std::get<idx>(arg_tuple)) ...
|
||||
);
|
||||
#ifdef AUTOCXXPY_INCLUDED_PYBIND11
|
||||
try
|
||||
{
|
||||
#endif
|
||||
// resolve all value:
|
||||
// if it was originally a pointer, then use pointer type.
|
||||
// if it was originally a value, just keep a reference to that value.
|
||||
sync<arg_types ...>(
|
||||
instance, py_func_name,
|
||||
arg_helper::loader<brigand::at<brigand::list<arg_types ...>, brigand::integral_constant<int, idx> > >{}
|
||||
(std::get<idx>(arg_tuple)) ...
|
||||
);
|
||||
#ifdef AUTOCXXPY_INCLUDED_PYBIND11
|
||||
}
|
||||
catch (const async_dispatch_exception &e)
|
||||
{
|
||||
async_callback_exception_handler::handle_excepiton(e);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
dispatcher::instance().add(std::move(task));
|
||||
}
|
||||
|
@ -8,12 +8,30 @@
|
||||
|
||||
|
||||
#ifndef AUTOCXXPY_UNUSED
|
||||
#define AUTOCXXPY_UNUSED(x) (void)(x)
|
||||
# define AUTOCXXPY_UNUSED(x) (void)(x)
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define AUTOCXXPY_SELECT_ANY __declspec(selectany)
|
||||
# define AUTOCXXPY_SELECT_ANY __declspec(selectany)
|
||||
|
||||
#else
|
||||
#define AUTOCXXPY_SELECT_ANY __attribute__ ((selectany))
|
||||
#endif
|
||||
# define AUTOCXXPY_SELECT_ANY __attribute__ ((selectany))
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __has_cpp_attribute
|
||||
# if __has_cpp_attribute(likely)
|
||||
# define AUTOCXXPY_LIKELY [[likely]]
|
||||
# endif
|
||||
# if __has_cpp_attribute(unlikely)
|
||||
# define AUTOCXXPY_UNLIKELY [[unlikely]]
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef AUTOCXXPY_LIKELY
|
||||
#define AUTOCXXPY_LIKELY
|
||||
#endif
|
||||
|
||||
#ifndef AUTOCXXPY_UNLIKELY
|
||||
#define AUTOCXXPY_UNLIKELY
|
||||
#endif
|
||||
|
@ -119,6 +119,7 @@
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<DisableSpecificWarnings>4819</DisableSpecificWarnings>
|
||||
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
@ -138,6 +139,7 @@
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<DisableSpecificWarnings>4819</DisableSpecificWarnings>
|
||||
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
@ -160,6 +162,7 @@
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<DisableSpecificWarnings>4819</DisableSpecificWarnings>
|
||||
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
@ -184,6 +187,7 @@
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<DisableSpecificWarnings>4819</DisableSpecificWarnings>
|
||||
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
|
@ -7,5 +7,20 @@ if typing.TYPE_CHECKING:
|
||||
from .vnxtp import *
|
||||
|
||||
|
||||
def set_async_callback_exception_handler(handler: Callable[[Exception, object, str], 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.
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
class AsyncDispatchException:
|
||||
what: str
|
||||
instance: object
|
||||
function_name: str
|
||||
|
||||
|
||||
from . import vnxtp_XTP_API as API
|
||||
|
||||
|
@ -7,6 +7,21 @@ if typing.TYPE_CHECKING:
|
||||
from .vnxtp import *
|
||||
|
||||
|
||||
def set_async_callback_exception_handler(handler: Callable[[Exception, object, str], 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.
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
class AsyncDispatchException:
|
||||
what: str
|
||||
instance: object
|
||||
function_name: str
|
||||
|
||||
|
||||
class TraderSpi():
|
||||
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
import sys
|
||||
from typing import Any, Sequence
|
||||
|
||||
from vnpy.api.xtp.vnxtp import (
|
||||
@ -12,21 +13,21 @@ from vnpy.api.xtp.vnxtp import (
|
||||
XTP_EXCHANGE_TYPE,
|
||||
XTP_LOG_LEVEL,
|
||||
XTP_PROTOCOL_TYPE,
|
||||
XTP_TICKER_TYPE_STOCK,
|
||||
XTP_TICKER_TYPE_INDEX,
|
||||
XTP_TICKER_TYPE_FUND,
|
||||
XTP_TICKER_TYPE_BOND,
|
||||
XTP_TICKER_TYPE_OPTION,
|
||||
XTP_PROTOCOL_TCP,
|
||||
XTP_PROTOCOL_UDP
|
||||
set_async_callback_exception_handler,
|
||||
AsyncDispatchException,
|
||||
XTP_TICKER_TYPE,
|
||||
)
|
||||
|
||||
from vnpy.event import EventEngine
|
||||
from vnpy.trader.constant import Exchange, Product
|
||||
from vnpy.trader.gateway import BaseGateway
|
||||
from vnpy.trader.object import (CancelRequest, OrderRequest, SubscribeRequest,
|
||||
TickData, ContractData, OrderData, TradeData,
|
||||
PositionData, AccountData)
|
||||
from vnpy.trader.object import (
|
||||
CancelRequest,
|
||||
OrderRequest,
|
||||
SubscribeRequest,
|
||||
TickData,
|
||||
ContractData,
|
||||
)
|
||||
from vnpy.trader.utility import get_folder_path
|
||||
|
||||
API = XTP.API
|
||||
@ -38,19 +39,17 @@ EXCHANGE_XTP2VT = {
|
||||
EXCHANGE_VT2XTP = {v: k for k, v in EXCHANGE_XTP2VT.items()}
|
||||
|
||||
PRODUCT_XTP2VT = {
|
||||
XTP_TICKER_TYPE_STOCK: Product.EQUITY,
|
||||
XTP_TICKER_TYPE_INDEX: Product.INDEX,
|
||||
XTP_TICKER_TYPE_FUND: Product.FUND,
|
||||
XTP_TICKER_TYPE_BOND: Product.BOND,
|
||||
XTP_TICKER_TYPE_OPTION: Product.OPTION
|
||||
XTP_TICKER_TYPE.XTP_TICKER_TYPE_STOCK: Product.EQUITY,
|
||||
XTP_TICKER_TYPE.XTP_TICKER_TYPE_INDEX: Product.INDEX,
|
||||
XTP_TICKER_TYPE.XTP_TICKER_TYPE_FUND: Product.FUND,
|
||||
XTP_TICKER_TYPE.XTP_TICKER_TYPE_BOND: Product.BOND,
|
||||
XTP_TICKER_TYPE.XTP_TICKER_TYPE_OPTION: Product.OPTION,
|
||||
}
|
||||
|
||||
|
||||
symbol_name_map = {}
|
||||
|
||||
|
||||
class XtpGateway(BaseGateway):
|
||||
|
||||
default_setting = {
|
||||
"账号": "",
|
||||
"密码": "",
|
||||
@ -59,7 +58,7 @@ class XtpGateway(BaseGateway):
|
||||
"行情端口": 0,
|
||||
"交易地址": "",
|
||||
"交易端口": 0,
|
||||
"行情协议": ["TCP", "UDP"]
|
||||
"行情协议": ["TCP", "UDP"],
|
||||
}
|
||||
|
||||
def __init__(self, event_engine: EventEngine):
|
||||
@ -68,19 +67,23 @@ class XtpGateway(BaseGateway):
|
||||
|
||||
self.quote_api = XtpQuoteApi(self)
|
||||
|
||||
set_async_callback_exception_handler(self._async_callback_exception_handler)
|
||||
pass
|
||||
|
||||
def connect(self, setting: dict):
|
||||
""""""
|
||||
userid = setting['账号']
|
||||
password = setting['密码']
|
||||
client_id = setting['客户号']
|
||||
quote_ip = setting['行情地址']
|
||||
quote_port = setting['行情端口']
|
||||
trade_ip = setting['交易地址']
|
||||
trade_port = setting['交易端口']
|
||||
userid = setting["账号"]
|
||||
password = setting["密码"]
|
||||
client_id = int(setting["客户号"])
|
||||
quote_ip = setting["行情地址"]
|
||||
quote_port = int(setting["行情端口"])
|
||||
trade_ip = setting["交易地址"]
|
||||
trade_port = setting["交易端口"]
|
||||
quote_protocol = setting["行情协议"]
|
||||
|
||||
self.quote_api.connect(userid, password, client_id,
|
||||
quote_ip, quote_port, quote_protocol)
|
||||
self.quote_api.connect(
|
||||
userid, password, client_id, quote_ip, quote_port, quote_protocol
|
||||
)
|
||||
|
||||
def close(self):
|
||||
""""""
|
||||
@ -102,11 +105,17 @@ class XtpGateway(BaseGateway):
|
||||
def query_position(self):
|
||||
pass
|
||||
|
||||
def _async_callback_exception_handler(self, e: AsyncDispatchException):
|
||||
error_str = f"发生内部错误:\n" f"位置:{e.instance}.{e.function_name}" f"详细信息:{e.what}"
|
||||
print(error_str, file=sys.stderr)
|
||||
|
||||
self.write_log(error_str) # write_error function?
|
||||
|
||||
|
||||
class XtpQuoteApi(API.QuoteSpi):
|
||||
|
||||
def __init__(self, gateway: BaseGateway):
|
||||
""""""
|
||||
super(XtpQuoteApi, self).__init__()
|
||||
self.gateway = gateway
|
||||
self.gateway_name = gateway.gateway_name
|
||||
|
||||
@ -123,10 +132,10 @@ class XtpQuoteApi(API.QuoteSpi):
|
||||
self,
|
||||
userid: str,
|
||||
password: str,
|
||||
client_id: str,
|
||||
client_id: int,
|
||||
server_ip: str,
|
||||
server_port: str,
|
||||
quote_protocol: str
|
||||
server_port: int,
|
||||
quote_protocol: str,
|
||||
):
|
||||
""""""
|
||||
if self.api:
|
||||
@ -139,17 +148,15 @@ class XtpQuoteApi(API.QuoteSpi):
|
||||
self.server_port = server_port
|
||||
|
||||
if quote_protocol == "CTP":
|
||||
self.quote_protocol = XTP_PROTOCOL_TCP
|
||||
self.quote_protocol = XTP_PROTOCOL_TYPE.XTP_PROTOCOL_TCP
|
||||
else:
|
||||
self.quote_protocol = XTP_PROTOCOL_UDP
|
||||
self.quote_protocol = XTP_PROTOCOL_TYPE.XTP_PROTOCOL_UDP
|
||||
|
||||
# Create API object
|
||||
path = str(get_folder_path(self.gateway_name.lower()))
|
||||
|
||||
self.api = API.QuoteApi.CreateQuoteApi(
|
||||
self.client_id,
|
||||
path,
|
||||
XTP_LOG_LEVEL.XTP_LOG_LEVEL_TRACE
|
||||
self.client_id, path, XTP_LOG_LEVEL.XTP_LOG_LEVEL_TRACE
|
||||
)
|
||||
|
||||
self.api.RegisterSpi(self)
|
||||
@ -161,7 +168,7 @@ class XtpQuoteApi(API.QuoteSpi):
|
||||
self.server_port,
|
||||
self.userid,
|
||||
self.password,
|
||||
self.quote_protocol
|
||||
self.quote_protocol,
|
||||
)
|
||||
|
||||
if not ret:
|
||||
@ -180,11 +187,13 @@ class XtpQuoteApi(API.QuoteSpi):
|
||||
def query_contract(self):
|
||||
""""""
|
||||
for exchange_id in EXCHANGE_XTP2VT.keys():
|
||||
self.api.QueryAllTickers(exchange_id)
|
||||
ret = self.api.QueryAllTickers(exchange_id)
|
||||
if ret != 0:
|
||||
self.gateway.write_log("订阅合约失败")
|
||||
|
||||
def check_error(self, func_name: str, error_info: XTPRspInfoStruct):
|
||||
""""""
|
||||
if error_info.error_id:
|
||||
if error_info and error_info.error_id:
|
||||
msg = f"{func_name}发生错误, 代码:{error_info.error_id},信息:{error_info.error_msg}"
|
||||
self.gateway.write_log(msg)
|
||||
return True
|
||||
@ -199,21 +208,37 @@ class XtpQuoteApi(API.QuoteSpi):
|
||||
""""""
|
||||
self.check_error("行情接口", error_info)
|
||||
|
||||
def OnSubMarketData(self, ticker: XTPSpecificTickerStruct, error_info: XTPRspInfoStruct,
|
||||
is_last: bool) -> Any:
|
||||
def OnSubMarketData(
|
||||
self,
|
||||
ticker: XTPSpecificTickerStruct,
|
||||
error_info: XTPRspInfoStruct,
|
||||
is_last: bool,
|
||||
) -> Any:
|
||||
""""""
|
||||
self.check_error("订阅行情", error_info)
|
||||
return super().OnSubMarketData(ticker, error_info, is_last)
|
||||
|
||||
def OnUnSubMarketData(self, ticker: XTPSpecificTickerStruct, error_info: XTPRspInfoStruct,
|
||||
is_last: bool) -> Any:
|
||||
def OnUnSubMarketData(
|
||||
self,
|
||||
ticker: XTPSpecificTickerStruct,
|
||||
error_info: XTPRspInfoStruct,
|
||||
is_last: bool,
|
||||
) -> Any:
|
||||
""""""
|
||||
pass
|
||||
|
||||
def OnDepthMarketData(self, market_data: XTPMarketDataStruct, bid1_qty: Sequence[int],
|
||||
bid1_count: int, max_bid1_count: int, ask1_qty: Sequence[int],
|
||||
ask1_count: int, max_ask1_count: int) -> Any:
|
||||
def OnDepthMarketData(
|
||||
self,
|
||||
market_data: XTPMarketDataStruct,
|
||||
bid1_qty: Sequence[int],
|
||||
bid1_count: int,
|
||||
max_bid1_count: int,
|
||||
ask1_qty: Sequence[int],
|
||||
ask1_count: int,
|
||||
max_ask1_count: int,
|
||||
) -> Any:
|
||||
""""""
|
||||
timestamp = market_data.date_time
|
||||
timestamp = market_data.data_time
|
||||
|
||||
tick = TickData(
|
||||
symbol=market_data.ticker,
|
||||
@ -247,19 +272,27 @@ class XtpQuoteApi(API.QuoteSpi):
|
||||
ask_volume_3=market_data.ask_qty[2],
|
||||
ask_volume_4=market_data.ask_qty[3],
|
||||
ask_volume_5=market_data.ask_qty[4],
|
||||
gateway_name=self.gateway_name
|
||||
gateway_name=self.gateway_name,
|
||||
)
|
||||
tick.name = symbol_name_map.get(tick.vt_symbol, tick.symbol)
|
||||
|
||||
self.gateway.on_tick(tick)
|
||||
|
||||
def OnSubOrderBook(self, ticker: XTPSpecificTickerStruct, error_info: XTPRspInfoStruct,
|
||||
is_last: bool) -> Any:
|
||||
def OnSubOrderBook(
|
||||
self,
|
||||
ticker: XTPSpecificTickerStruct,
|
||||
error_info: XTPRspInfoStruct,
|
||||
is_last: bool,
|
||||
) -> Any:
|
||||
""""""
|
||||
pass
|
||||
|
||||
def OnUnSubOrderBook(self, ticker: XTPSpecificTickerStruct, error_info: XTPRspInfoStruct,
|
||||
is_last: bool) -> Any:
|
||||
def OnUnSubOrderBook(
|
||||
self,
|
||||
ticker: XTPSpecificTickerStruct,
|
||||
error_info: XTPRspInfoStruct,
|
||||
is_last: bool,
|
||||
) -> Any:
|
||||
""""""
|
||||
pass
|
||||
|
||||
@ -267,13 +300,21 @@ class XtpQuoteApi(API.QuoteSpi):
|
||||
""""""
|
||||
pass
|
||||
|
||||
def OnSubTickByTick(self, ticker: XTPSpecificTickerStruct, error_info: XTPRspInfoStruct,
|
||||
is_last: bool) -> Any:
|
||||
def OnSubTickByTick(
|
||||
self,
|
||||
ticker: XTPSpecificTickerStruct,
|
||||
error_info: XTPRspInfoStruct,
|
||||
is_last: bool,
|
||||
) -> Any:
|
||||
""""""
|
||||
pass
|
||||
|
||||
def OnUnSubTickByTick(self, ticker: XTPSpecificTickerStruct, error_info: XTPRspInfoStruct,
|
||||
is_last: bool) -> Any:
|
||||
def OnUnSubTickByTick(
|
||||
self,
|
||||
ticker: XTPSpecificTickerStruct,
|
||||
error_info: XTPRspInfoStruct,
|
||||
is_last: bool,
|
||||
) -> Any:
|
||||
""""""
|
||||
pass
|
||||
|
||||
@ -281,88 +322,106 @@ class XtpQuoteApi(API.QuoteSpi):
|
||||
""""""
|
||||
pass
|
||||
|
||||
def OnSubscribeAllMarketData(self, exchange_id: XTP_EXCHANGE_TYPE,
|
||||
error_info: XTPRspInfoStruct) -> Any:
|
||||
def OnSubscribeAllMarketData(
|
||||
self, exchange_id: XTP_EXCHANGE_TYPE, error_info: XTPRspInfoStruct
|
||||
) -> Any:
|
||||
""""""
|
||||
pass
|
||||
|
||||
def OnUnSubscribeAllMarketData(self, exchange_id: XTP_EXCHANGE_TYPE,
|
||||
error_info: XTPRspInfoStruct) -> Any:
|
||||
def OnUnSubscribeAllMarketData(
|
||||
self, exchange_id: XTP_EXCHANGE_TYPE, error_info: XTPRspInfoStruct
|
||||
) -> Any:
|
||||
""""""
|
||||
pass
|
||||
|
||||
def OnSubscribeAllOrderBook(self, exchange_id: XTP_EXCHANGE_TYPE,
|
||||
error_info: XTPRspInfoStruct) -> Any:
|
||||
def OnSubscribeAllOrderBook(
|
||||
self, exchange_id: XTP_EXCHANGE_TYPE, error_info: XTPRspInfoStruct
|
||||
) -> Any:
|
||||
""""""
|
||||
pass
|
||||
|
||||
def OnUnSubscribeAllOrderBook(self, exchange_id: XTP_EXCHANGE_TYPE,
|
||||
error_info: XTPRspInfoStruct) -> Any:
|
||||
def OnUnSubscribeAllOrderBook(
|
||||
self, exchange_id: XTP_EXCHANGE_TYPE, error_info: XTPRspInfoStruct
|
||||
) -> Any:
|
||||
""""""
|
||||
pass
|
||||
|
||||
def OnSubscribeAllTickByTick(self, exchange_id: XTP_EXCHANGE_TYPE,
|
||||
error_info: XTPRspInfoStruct) -> Any:
|
||||
def OnSubscribeAllTickByTick(
|
||||
self, exchange_id: XTP_EXCHANGE_TYPE, error_info: XTPRspInfoStruct
|
||||
) -> Any:
|
||||
""""""
|
||||
pass
|
||||
|
||||
def OnUnSubscribeAllTickByTick(self, exchange_id: XTP_EXCHANGE_TYPE,
|
||||
error_info: XTPRspInfoStruct) -> Any:
|
||||
def OnUnSubscribeAllTickByTick(
|
||||
self, exchange_id: XTP_EXCHANGE_TYPE, error_info: XTPRspInfoStruct
|
||||
) -> Any:
|
||||
""""""
|
||||
pass
|
||||
|
||||
def OnQueryAllTickers(self, ticker_info: XTPQuoteStaticInfo, error_info: XTPRspInfoStruct,
|
||||
is_last: bool) -> Any:
|
||||
""""""
|
||||
return
|
||||
# if self.check_error("查询合约", error_info):
|
||||
# return
|
||||
def OnQueryAllTickers(
|
||||
self,
|
||||
ticker_info: XTPQuoteStaticInfo,
|
||||
error_info: XTPRspInfoStruct,
|
||||
is_last: bool,
|
||||
) -> Any:
|
||||
if self.check_error("查询合约", error_info):
|
||||
return
|
||||
|
||||
# contract = ContractData(
|
||||
# symbol=ticker_info.ticker,
|
||||
# exchange=EXCHANGE_XTP2VT[ticker_info.exchange_id],
|
||||
# name=ticker_info.ticker_name,
|
||||
# product=PRODUCT_XTP2VT[ticker_info.ticker_type],
|
||||
# size=1,
|
||||
# pricetick=ticker_info.pricetick,
|
||||
# min_volume=ticker_info.buy_qty_unit,
|
||||
# gateway_name=self.gateway_name
|
||||
# )
|
||||
# self.gateway.on_contract(contract)
|
||||
contract = ContractData(
|
||||
symbol=ticker_info.ticker,
|
||||
exchange=EXCHANGE_XTP2VT[ticker_info.exchange_id],
|
||||
name=ticker_info.ticker_name,
|
||||
product=PRODUCT_XTP2VT[ticker_info.ticker_type],
|
||||
size=1,
|
||||
pricetick=ticker_info.pricetick,
|
||||
min_volume=ticker_info.buy_qty_unit,
|
||||
gateway_name=self.gateway_name,
|
||||
)
|
||||
self.gateway.on_contract(contract)
|
||||
|
||||
# symbol_name_map[contract.vt_symbol] = contract.name
|
||||
symbol_name_map[contract.vt_symbol] = contract.name
|
||||
|
||||
def OnQueryTickersPriceInfo(self, ticker_info: XTPTickerPriceInfo, error_info: XTPRspInfoStruct,
|
||||
is_last: bool) -> Any:
|
||||
def OnQueryTickersPriceInfo(
|
||||
self,
|
||||
ticker_info: XTPTickerPriceInfo,
|
||||
error_info: XTPRspInfoStruct,
|
||||
is_last: bool,
|
||||
) -> Any:
|
||||
""""""
|
||||
pass
|
||||
|
||||
def OnSubscribeAllOptionMarketData(self, exchange_id: XTP_EXCHANGE_TYPE,
|
||||
error_info: XTPRspInfoStruct) -> Any:
|
||||
def OnSubscribeAllOptionMarketData(
|
||||
self, exchange_id: XTP_EXCHANGE_TYPE, error_info: XTPRspInfoStruct
|
||||
) -> Any:
|
||||
""""""
|
||||
pass
|
||||
|
||||
def OnUnSubscribeAllOptionMarketData(self, exchange_id: XTP_EXCHANGE_TYPE,
|
||||
error_info: XTPRspInfoStruct) -> Any:
|
||||
def OnUnSubscribeAllOptionMarketData(
|
||||
self, exchange_id: XTP_EXCHANGE_TYPE, error_info: XTPRspInfoStruct
|
||||
) -> Any:
|
||||
""""""
|
||||
pass
|
||||
|
||||
def OnSubscribeAllOptionOrderBook(self, exchange_id: XTP_EXCHANGE_TYPE,
|
||||
error_info: XTPRspInfoStruct) -> Any:
|
||||
def OnSubscribeAllOptionOrderBook(
|
||||
self, exchange_id: XTP_EXCHANGE_TYPE, error_info: XTPRspInfoStruct
|
||||
) -> Any:
|
||||
""""""
|
||||
pass
|
||||
|
||||
def OnUnSubscribeAllOptionOrderBook(self, exchange_id: XTP_EXCHANGE_TYPE,
|
||||
error_info: XTPRspInfoStruct) -> Any:
|
||||
def OnUnSubscribeAllOptionOrderBook(
|
||||
self, exchange_id: XTP_EXCHANGE_TYPE, error_info: XTPRspInfoStruct
|
||||
) -> Any:
|
||||
""""""
|
||||
pass
|
||||
|
||||
def OnSubscribeAllOptionTickByTick(self, exchange_id: XTP_EXCHANGE_TYPE,
|
||||
error_info: XTPRspInfoStruct) -> Any:
|
||||
def OnSubscribeAllOptionTickByTick(
|
||||
self, exchange_id: XTP_EXCHANGE_TYPE, error_info: XTPRspInfoStruct
|
||||
) -> Any:
|
||||
""""""
|
||||
pass
|
||||
|
||||
def OnUnSubscribeAllOptionTickByTick(self, exchange_id: XTP_EXCHANGE_TYPE,
|
||||
error_info: XTPRspInfoStruct) -> Any:
|
||||
def OnUnSubscribeAllOptionTickByTick(
|
||||
self, exchange_id: XTP_EXCHANGE_TYPE, error_info: XTPRspInfoStruct
|
||||
) -> Any:
|
||||
""""""
|
||||
pass
|
||||
|
Loading…
Reference in New Issue
Block a user