#include <Windows.h>
#include <libloaderapi.h>
#include <errhandlingapi.h>

#include <iostream>
#include <vector>

#include "spdOrderAPI.h"

static HMODULE hSpeedyDLL = NULL;
fptrPyOrderAdapter_New pyOrderAdapter_New = NULL;
fptrPyOrderAdapter_Delete pyOrderAdapter_Delete = NULL;
fptrPyOrderAdapter_IsConnected pyOrderAdapter_IsConnected = NULL;
fptrPyOrderAdapter_Connect pyOrderAdapter_Connect = NULL;
fptrPyOrderAdapter_LogonProxy pyOrderAdapter_LogonProxy = NULL;
fptrPyOrderAdapter_SetAccount pyOrderAdapter_SetAccount = NULL;
fptrPyOrderAdapter_Disconnect pyOrderAdapter_Disconnect = NULL;
fptrPyOrderAdapter_SendNewForeignOrder pyOrderAdapter_SendNewForeignOrder = NULL;
fptrPyOrderAdapter_SendNewOrderEx pyOrderAdapter_SendNewOrderEx = NULL;
fptrPyOrderAdapter_SendCancelForeignOrder pyOrderAdapter_SendCancelForeignOrder = NULL;
fptrPyOrderAdapter_SendCancelOrderEx pyOrderAdapter_SendCancelOrderEx = NULL;
fptrPyOrderAdapter_SendReplaceOrderEx pyOrderAdapter_SendReplaceOrderEx = NULL;
fptrPyOrderAdapter_RegEvents pyOrderAdapter_RegEvents = NULL;
fptrPyOrderAdapter_GetLastErrorMessage pyOrderAdapter_GetLastErrorMessage = NULL;
fptrPyOrderAdapter_EnableMegaCA pyOrderAdapter_EnableMegaCA = NULL;
fptrPyOrderAdapter_CreateQueryParam pyOrderAdapter_CreateQueryParam = NULL;
fptrPyOrderAdapter_FreeQueryParam pyOrderAdapter_FreeQueryParam = NULL;
fptrPyOrderAdapter_AddQueryParam  pyOrderAdapter_AddQueryParam = NULL;
fptrPyOrderAdapter_GetStringFromQueryResult pyOrderAdapter_GetStringFromQueryResult = NULL;
fptrPyOrderAdapter_FreeQueryResult pyOrderAdapter_FreeQueryResult = NULL;
fptrPyOrderAdapter_ChangePassword  pyOrderAdapter_ChangePassword = NULL;
fptrPyOrderAdapter_MakeStockAccountInquriy pyOrderAdapter_MakeStockAccountInquriy = NULL;
fptrPyOrderAdapter_QueryStkOrder pyOrderAdapter_QueryStkOrder = NULL;
fptrPyOrderAdapter_QueryStkMatch pyOrderAdapter_QueryStkMatch = NULL;
fptrPyOrderAdapter_QueryFutOrder pyOrderAdapter_QueryFutOrder = NULL;
fptrPyOrderAdapter_QueryFutMatch pyOrderAdapter_QueryFutMatch = NULL;
fptrPyOrderAdapter_QueryFutUncoverRT pyOrderAdapter_QueryFutUncoverRT = NULL;
fptrPyOrderAdapter_QueryMargin pyOrderAdapter_QueryMargin = NULL;
fptrpyOrderAdapter_QueryForeignStockInventory pyOrderAdapter_QueryForeignStockInventory = NULL;
fptrpyOrderAdapter_QueryForeignStockOrder pyOrderAdapter_QueryForeignStockOrder = NULL;
fptrpyOrderAdapter_QueryForeignStockFilled pyOrderAdapter_QueryForeignStockFilled = NULL;;
fptrpyOrderAdapter_DownloadForeignStockProductData pyOrderAdapter_DownloadForeignStockProductData = NULL;
fptrpyOrderAdapter_DownloadForeignStockCurrencyData pyOrderAdapter_DownloadForeignStockCurrencyData = NULL;
fptrpyOrderAdapter_DownloadForeignStockMarketData pyOrderAdapter_DownloadForeignStockMarketData = NULL;
fptrpyOrderAdapter_GetMKChartData pyOrderAdapter_GetMKChartData = NULL;
fptrpyOrderAdapter_GetWKChartData pyOrderAdapter_GetWKChartData = NULL;
fptrpyOrderAdapter_GetDKChartData pyOrderAdapter_GetDKChartData = NULL;
fptrpyOrderAdapter_GetAdjustedDKChartData pyOrderAdapter_GetAdjustedDKChartData = NULL;
fptrpyOrderAdapter_GetAdjustedWKChartData pyOrderAdapter_GetAdjustedWKChartData = NULL;
fptrpyOrderAdapter_GetAdjustedMKChartData pyOrderAdapter_GetAdjustedMKChartData = NULL;

bool spdOrderAPI::LoadOrderAPIFromDLL()
{
#ifdef _M_X64
	std::string dll_name = "megaSpeedyAPI_64.dll";
#else
	std::string dll_name = "megaSpeedyAPI.dll";
#endif

	if (hSpeedyDLL)
		return true;

	hSpeedyDLL = LoadLibraryA(dll_name.c_str());
	if (!hSpeedyDLL)
	{
		DWORD err = GetLastError();
		std::cout << "Load " << dll_name << " fail! Error Code:" << err << std::endl;
		return false;
	}

	std::vector<std::pair<void*, std::string>> exported_function;

	pyOrderAdapter_New = (fptrPyOrderAdapter_New)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_New");
	pyOrderAdapter_Delete = (fptrPyOrderAdapter_Delete)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_Delete");
	pyOrderAdapter_IsConnected = (fptrPyOrderAdapter_IsConnected)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_IsConnected");
	pyOrderAdapter_Connect = (fptrPyOrderAdapter_Connect)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_Connect");
	pyOrderAdapter_LogonProxy = (fptrPyOrderAdapter_LogonProxy)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_LogonProxy");
	pyOrderAdapter_SetAccount = (fptrPyOrderAdapter_SetAccount)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_SetAccount");
	pyOrderAdapter_Disconnect = (fptrPyOrderAdapter_Disconnect)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_Disconnect");
	pyOrderAdapter_SendNewForeignOrder = (fptrPyOrderAdapter_SendNewForeignOrder)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_SendNewForeignOrder");
	pyOrderAdapter_SendNewOrderEx = (fptrPyOrderAdapter_SendNewOrderEx)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_SendNewOrderEx");
	pyOrderAdapter_SendCancelForeignOrder = (fptrPyOrderAdapter_SendCancelForeignOrder)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_SendCancelForeignOrder");
	pyOrderAdapter_SendCancelOrderEx = (fptrPyOrderAdapter_SendCancelOrderEx)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_SendCancelOrderEx");
	pyOrderAdapter_SendReplaceOrderEx = (fptrPyOrderAdapter_SendReplaceOrderEx)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_SendReplaceOrderEx");
	pyOrderAdapter_RegEvents = (fptrPyOrderAdapter_RegEvents)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_RegEvents");
	pyOrderAdapter_GetLastErrorMessage = (fptrPyOrderAdapter_GetLastErrorMessage)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_GetLastErrorMessage");
	pyOrderAdapter_EnableMegaCA = (fptrPyOrderAdapter_EnableMegaCA)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_EnableMegaCA");
	pyOrderAdapter_CreateQueryParam = (fptrPyOrderAdapter_CreateQueryParam)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_CreateQueryParam");
	pyOrderAdapter_FreeQueryParam = (fptrPyOrderAdapter_FreeQueryParam)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_FreeQueryParam");
	pyOrderAdapter_AddQueryParam = (fptrPyOrderAdapter_AddQueryParam)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_AddQueryParam");
	pyOrderAdapter_GetStringFromQueryResult = (fptrPyOrderAdapter_GetStringFromQueryResult)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_GetStringFromQueryResult");
	pyOrderAdapter_FreeQueryResult = (fptrPyOrderAdapter_FreeQueryResult)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_FreeQueryResult");
	pyOrderAdapter_ChangePassword = (fptrPyOrderAdapter_ChangePassword)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_ChangePassword");
	pyOrderAdapter_MakeStockAccountInquriy = (fptrPyOrderAdapter_MakeStockAccountInquriy)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_MakeStockAccountInquriy");
	pyOrderAdapter_QueryStkOrder = (fptrPyOrderAdapter_QueryStkOrder)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_QueryStkOrder");
	pyOrderAdapter_QueryStkMatch = (fptrPyOrderAdapter_QueryStkMatch)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_QueryStkMatch");
	pyOrderAdapter_QueryFutOrder = (fptrPyOrderAdapter_QueryFutOrder)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_QueryFutOrder");
	pyOrderAdapter_QueryFutMatch = (fptrPyOrderAdapter_QueryFutMatch)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_QueryFutMatch");
	pyOrderAdapter_QueryFutUncoverRT = (fptrPyOrderAdapter_QueryFutUncoverRT)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_QueryFutUncoverRT");
	pyOrderAdapter_QueryMargin = (fptrPyOrderAdapter_QueryMargin)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_QueryMargin");
	pyOrderAdapter_QueryForeignStockInventory = (fptrpyOrderAdapter_QueryForeignStockInventory)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_QueryForeignStockInventory");
	pyOrderAdapter_QueryForeignStockOrder = (fptrpyOrderAdapter_QueryForeignStockOrder)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_QueryForeignStockOrder");
	pyOrderAdapter_QueryForeignStockFilled = (fptrpyOrderAdapter_QueryForeignStockFilled)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_QueryForeignStockFilled");
	pyOrderAdapter_DownloadForeignStockProductData = (fptrpyOrderAdapter_DownloadForeignStockProductData)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_DownloadForeignStockProductData");
	pyOrderAdapter_DownloadForeignStockCurrencyData = (fptrpyOrderAdapter_DownloadForeignStockCurrencyData)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_DownloadForeignStockCurrencyData");
	pyOrderAdapter_DownloadForeignStockMarketData = (fptrpyOrderAdapter_DownloadForeignStockMarketData)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_DownloadForeignStockMarketData");

	pyOrderAdapter_GetMKChartData = (fptrpyOrderAdapter_GetMKChartData)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_GetMKChartData");
	pyOrderAdapter_GetWKChartData = (fptrpyOrderAdapter_GetWKChartData)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_GetWKChartData");
	pyOrderAdapter_GetDKChartData = (fptrpyOrderAdapter_GetDKChartData)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_GetDKChartData");
	pyOrderAdapter_GetAdjustedDKChartData = (fptrpyOrderAdapter_GetAdjustedDKChartData)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_GetAdjustedDKChartData");
	pyOrderAdapter_GetAdjustedWKChartData = (fptrpyOrderAdapter_GetAdjustedWKChartData)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_GetAdjustedWKChartData");
	pyOrderAdapter_GetAdjustedMKChartData = (fptrpyOrderAdapter_GetAdjustedMKChartData)GetProcAddress(hSpeedyDLL, "pyOrderAdapter_GetAdjustedMKChartData");

	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_New, "pyOrderAdapter_New"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_Delete, "pyOrderAdapter_Delete"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_IsConnected, "pyOrderAdapter_IsConnected"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_Connect, "pyOrderAdapter_Connect"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_LogonProxy, "pyOrderAdapter_LogonProxy"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_SetAccount, "pyOrderAdapter_SetAccount"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_Disconnect, "pyOrderAdapter_Disconnect"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_SendNewOrderEx, "pyOrderAdapter_SendNewOrderEx"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_SendCancelOrderEx, "pyOrderAdapter_SendCancelOrderEx"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_SendReplaceOrderEx, "pyOrderAdapter_SendReplaceOrderEx"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_SendNewForeignOrder, "pyOrderAdapter_SendNewForeignOrder"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_SendCancelForeignOrder, "pyOrderAdapter_SendCancelForeignOrder"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_RegEvents, "pyOrderAdapter_RegEvents"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_GetLastErrorMessage, "pyOrderAdapter_GetLastErrorMessage"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_EnableMegaCA, "pyOrderAdapter_EnableMegaCA"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_CreateQueryParam, "pyOrderAdapter_CreateQueryParam"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_FreeQueryParam, "pyOrderAdapter_FreeQueryParam"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_AddQueryParam, "pyOrderAdapter_AddQueryParam"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_GetStringFromQueryResult, "pyOrderAdapter_GetStringFromQueryResult"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_FreeQueryResult, "pyOrderAdapter_FreeQueryResult"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_ChangePassword, "pyOrderAdapter_ChangePassword"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_MakeStockAccountInquriy, "pyOrderAdapter_MakeStockAccountInquriy"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_QueryStkOrder, "pyOrderAdapter_QueryStkOrder"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_QueryStkMatch, "pyOrderAdapter_QueryStkMatch"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_QueryFutOrder, "pyOrderAdapter_QueryFutOrder"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_QueryFutMatch, "pyOrderAdapter_QueryFutMatch"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_QueryFutUncoverRT, "pyOrderAdapter_QueryFutUncoverRT"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_QueryMargin, "pyOrderAdapter_QueryMargin"));
	
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_QueryForeignStockInventory, "pyOrderAdapter_QueryForeignStockInventory"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_QueryForeignStockOrder, "pyOrderAdapter_QueryForeignStockOrder"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_QueryForeignStockFilled, "pyOrderAdapter_QueryForeignStockFilled"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_DownloadForeignStockProductData, "pyOrderAdapter_DownloadForeignStockProductData"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_DownloadForeignStockCurrencyData, "pyOrderAdapter_DownloadForeignStockCurrencyData"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_DownloadForeignStockMarketData, "pyOrderAdapter_DownloadForeignStockMarketData"));

	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_GetMKChartData, "pyOrderAdapter_GetMKChartData"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_GetWKChartData, "pyOrderAdapter_GetWKChartData"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_GetDKChartData, "pyOrderAdapter_GetDKChartData"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_GetAdjustedDKChartData, "pyOrderAdapter_GetAdjustedDKChartData"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_GetAdjustedWKChartData, "pyOrderAdapter_GetAdjustedWKChartData"));
	exported_function.push_back(std::pair<void*, std::string>(pyOrderAdapter_GetAdjustedMKChartData, "pyOrderAdapter_GetAdjustedMKChartData"));

	for (size_t i = 0; i < exported_function.size(); ++i)
	{
		if (!exported_function[i].first)
		{
			std::cout << "function \"" << exported_function[i].second << "\" is missing in " << dll_name << std::endl;
			FreeLibrary(hSpeedyDLL);
			hSpeedyDLL = NULL;

			return false;
		}
	}

	return true;
}

void spdOrderAPI::OnOrderConnected(void* user_defined)
{
	spdOrderAPI* target = reinterpret_cast<spdOrderAPI*>(user_defined);
	target->OnSpeedyConnected();
}

void spdOrderAPI::OnOrderDisconnected(void* user_defined)
{
	spdOrderAPI* target = reinterpret_cast<spdOrderAPI*>(user_defined);
	target->OnSpeedyDisconnected();
}

void spdOrderAPI::OnOrderLogonResponse(void* user_defined, bool isLoginOK, const char* ReplyMsg)
{
	spdOrderAPI* target = reinterpret_cast<spdOrderAPI*>(user_defined);
	target->OnSpeedyLogonResponse(isLoginOK, ReplyMsg);
}

void spdOrderAPI::OnReplyNewOrder(void* user_defined, long long nid, const char* UDD, const char* Symbol, double Price, const char* Side, long OrderQty, const char* OrderType, const char* TimeinForce, const char* OrderID)
{
	spdOrderAPI* target = reinterpret_cast<spdOrderAPI*>(user_defined);
	target->OnNewOrderReport(nid, UDD, Symbol, Price, Side, OrderQty, OrderType, TimeinForce, OrderID);
}

void spdOrderAPI::OnReplyCancelOrder(void* user_defined, long long nid, const char* UDD, const char* Symbol, double Price, const char* Side, const char* OrderID)
{
	spdOrderAPI* target = reinterpret_cast<spdOrderAPI*>(user_defined);
	target->OnCancelOrderReport(nid, UDD, Symbol, Price, Side, OrderID);
}

void spdOrderAPI::OnReplyReplaceOrder(void* user_defined, long long nid, const char* UDD, const char* Symbol, double Price, const char* Side, long OrderQty, const char* OrderType, const char* TimeinForce, const char* OrderID)
{
	spdOrderAPI* target = reinterpret_cast<spdOrderAPI*>(user_defined);
	target->OnReplaceOrderReport(nid, UDD, Symbol, Price, Side, OrderQty, OrderType, TimeinForce, OrderID);
}

void spdOrderAPI::OnOrderRejected(void* user_defined, long long nid, const char* UDD, const char* ActionFrom, const char* ErrCode, const char* ErrMsg)
{
	spdOrderAPI* target = reinterpret_cast<spdOrderAPI*>(user_defined);
	target->OnOrderRejectedReport(nid, UDD, ActionFrom, ErrCode, ErrMsg);
}

void spdOrderAPI::OnOrderFilled(void* user_defined, long long nid, const char* UDD, const char* OrderID, long ReportSeq, double MatchPrice, long MatchQty, const char* MatchTime)
{
	spdOrderAPI* target = reinterpret_cast<spdOrderAPI*>(user_defined);
	target->OnOrderMatchReport(nid, UDD, OrderID, ReportSeq, MatchPrice, MatchQty, MatchTime);
}

spdOrderAPI::spdOrderAPI():orderAPI(NULL)
{
	LoadOrderAPIFromDLL();
	orderAPI = pyOrderAdapter_New();
	pyOrderAdapter_RegEvents(orderAPI,
		                     this,
		                     OnOrderConnected,
		                     OnOrderDisconnected,
		                     OnOrderLogonResponse,
		                     OnReplyNewOrder,
		                     OnReplyCancelOrder,
		                     OnReplyReplaceOrder,
		                     OnOrderRejected,
		                     OnOrderFilled);
}

spdOrderAPI::~spdOrderAPI()
{
	if (orderAPI)
		pyOrderAdapter_Delete(orderAPI);
}

bool spdOrderAPI::IsSpeedyConnected(void)
{
	return pyOrderAdapter_IsConnected(orderAPI);
}

void spdOrderAPI::ConnectSpeedy(const char* IP, int Port, int TimeoutSec)
{
	pyOrderAdapter_Connect(orderAPI, IP, Port, TimeoutSec);
}

bool spdOrderAPI::LogonSpeedy(const char* ID, const char* Password, const char* Account)
{
	return pyOrderAdapter_LogonProxy(orderAPI, ID, Password, Account);
}

bool spdOrderAPI::SetAccount(const char* Exchange, const char* BrokerID, const char* Account)
{
	return  pyOrderAdapter_SetAccount(orderAPI, Exchange, BrokerID, Account);
}

void spdOrderAPI::DisconnectSpeedy(void)
{
	pyOrderAdapter_Disconnect(orderAPI);
}

long long spdOrderAPI::SendNewOrder(const char* Market,
	                                const char* UDD,
	                                const char* Symbol,
	                                double      Price,
	                                const char* Side,
	                                int         OrderQty,
	                                const char* OrderType,
	                                const char* TimeInForce,
	                                const char* TradingSession,
	                                const char* PositionEffect,
	                                const char* TWSEOrdType)
{
	return pyOrderAdapter_SendNewOrderEx(orderAPI,
		                                 Market,
		                                 UDD,
		                                 Symbol,
		                                 Price,
		                                 Side,
		                                 OrderQty,
		                                 OrderType,
		                                 TimeInForce,
		                                 TradingSession,
		                                 PositionEffect,
		                                 TWSEOrdType);
}

long long spdOrderAPI::SendNewForeignOrder(const char* Exchange,
	                                       const char* UDD,
	                                       const char* Symbol,
	                                       double      Price,
	                                       double      StopPrice,
	                                       const char* Side,
	                                       int         OrderQty,
	                                       const char* OrderType,
	                                       const char* TimeInForce,
	                                       const char* Currency,
	                                       const char* ExecInst)
{
	return pyOrderAdapter_SendNewForeignOrder(orderAPI,
		                                      Exchange,
		                                      UDD,
		                                      Symbol,
		                                      Price,
		                                      StopPrice,
		                                      Side,
		                                      OrderQty,
		                                      OrderType,
		                                      TimeInForce,
		                                      Currency,
		                                      ExecInst);
}

long long spdOrderAPI::SendCancelOrder(const char* Market,
	                                   const char* UDD,
	                                   const char* Symbol,
	                                   double      Price,
	                                   const char* Side,
	                                   const char* OrderID,
	                                   const char* TradingSession,
	                                   const char* TWSEOrdType)
{
	return pyOrderAdapter_SendCancelOrderEx(orderAPI,
		                                    Market,
		                                    UDD,
		                                    Symbol,
		                                    Price,
		                                    Side,
		                                    OrderID,
		                                    TradingSession,
		                                    TWSEOrdType);
}

long long spdOrderAPI::SendCancelForeignOrder(const char* Exchange,
	                                          const char* UDD,
	                                          const char* Symbol,
	                                          const char* Side,
	                                          const char* OrderID)
{
	return pyOrderAdapter_SendCancelForeignOrder(orderAPI,
		                                         Exchange,
		                                         UDD,
		                                         Symbol,
		                                         Side,
		                                         OrderID);
}

long long spdOrderAPI::SendReplaceOrder(const char* Market,
	                                    const char* UDD,
	                                    const char* Symbol,
	                                    const char* OrderID,
	                                    const char* Side,
	                                    double      Price,
	                                    int         OrderQty,
	                                    const char* OrderType,
	                                    const char* TimeInForce,
	                                    const char* TradingSession,
	                                    const char* TWSEOrdType)
{
	return pyOrderAdapter_SendReplaceOrderEx(orderAPI,
		                                     Market,
		                                     UDD,
		                                     Symbol,
		                                     OrderID,
		                                     Side,
		                                     Price,
		                                     OrderQty,
		                                     OrderType,
		                                     TimeInForce,
		                                     TradingSession,
		                                     TWSEOrdType);
}

std::string spdOrderAPI::GetOrderAPILastErrorMessage()
{
	std::string err_msg = pyOrderAdapter_GetLastErrorMessage(orderAPI);
	return err_msg;
}

bool spdOrderAPI::EnableMegaCA(const char* pfx_path, const char* pfx_id, const char* pfx_pwd)
{
	return pyOrderAdapter_EnableMegaCA(orderAPI, pfx_path, pfx_id, pfx_pwd);
}

std::string spdOrderAPI::ChangePassword(const std::map<std::string, std::string>& query_param)
{
	void* qparam = pyOrderAdapter_CreateQueryParam();
	std::map<std::string, std::string>::const_iterator iter = query_param.cbegin();
	for (; iter != query_param.cend(); iter++)
		pyOrderAdapter_AddQueryParam(qparam, iter->first.c_str(), iter->second.c_str());

	void* qresult = pyOrderAdapter_ChangePassword(orderAPI, qparam);
	pyOrderAdapter_FreeQueryParam(qparam);
	std::string result = pyOrderAdapter_GetStringFromQueryResult(qresult, 0);
	pyOrderAdapter_FreeQueryResult(qresult);

	return result;
}

std::string spdOrderAPI::MakeStockAccountInquriy(const std::map<std::string, std::string>& query_param)
{
	void* qparam = pyOrderAdapter_CreateQueryParam();
	std::map<std::string, std::string>::const_iterator iter = query_param.cbegin();
	for (; iter != query_param.cend(); iter++)
		pyOrderAdapter_AddQueryParam(qparam, iter->first.c_str(), iter->second.c_str());

	void* qresult = pyOrderAdapter_MakeStockAccountInquriy(orderAPI, qparam);
	pyOrderAdapter_FreeQueryParam(qparam);
	std::string result = pyOrderAdapter_GetStringFromQueryResult(qresult, 0);
	pyOrderAdapter_FreeQueryResult(qresult);

	return result;
}

std::string spdOrderAPI::QueryStkOrder(const std::map<std::string, std::string>& query_param)
{
	void* qparam = pyOrderAdapter_CreateQueryParam();
	std::map<std::string, std::string>::const_iterator iter = query_param.cbegin();
	for (; iter != query_param.cend(); iter++)
		pyOrderAdapter_AddQueryParam(qparam, iter->first.c_str(), iter->second.c_str());

	void* qresult = pyOrderAdapter_QueryStkOrder(orderAPI, qparam);
	pyOrderAdapter_FreeQueryParam(qparam);
	std::string result = pyOrderAdapter_GetStringFromQueryResult(qresult, 0);
	pyOrderAdapter_FreeQueryResult(qresult);

	return result;
}

std::string spdOrderAPI::QueryStkMatch(const std::map<std::string, std::string>& query_param)
{
	void* qparam = pyOrderAdapter_CreateQueryParam();
	std::map<std::string, std::string>::const_iterator iter = query_param.cbegin();
	for (; iter != query_param.cend(); iter++)
		pyOrderAdapter_AddQueryParam(qparam, iter->first.c_str(), iter->second.c_str());

	void* qresult = pyOrderAdapter_QueryStkMatch(orderAPI, qparam);
	pyOrderAdapter_FreeQueryParam(qparam);
	std::string result = pyOrderAdapter_GetStringFromQueryResult(qresult, 0);
	pyOrderAdapter_FreeQueryResult(qresult);

	return result;
}

std::string spdOrderAPI::QueryFutOrder(const std::map<std::string, std::string>& query_param)
{
	void* qparam = pyOrderAdapter_CreateQueryParam();
	std::map<std::string, std::string>::const_iterator iter = query_param.cbegin();
	for (; iter != query_param.cend(); iter++)
		pyOrderAdapter_AddQueryParam(qparam, iter->first.c_str(), iter->second.c_str());

	void* qresult = pyOrderAdapter_QueryFutOrder(orderAPI, qparam);
	pyOrderAdapter_FreeQueryParam(qparam);
	std::string result = pyOrderAdapter_GetStringFromQueryResult(qresult, 0);
	pyOrderAdapter_FreeQueryResult(qresult);

	return result;
}

std::string spdOrderAPI::QueryFutMatch(const std::map<std::string, std::string>& query_param)
{
	void* qparam = pyOrderAdapter_CreateQueryParam();
	std::map<std::string, std::string>::const_iterator iter = query_param.cbegin();
	for (; iter != query_param.cend(); iter++)
		pyOrderAdapter_AddQueryParam(qparam, iter->first.c_str(), iter->second.c_str());

	void* qresult = pyOrderAdapter_QueryFutMatch(orderAPI, qparam);
	pyOrderAdapter_FreeQueryParam(qparam);
	std::string result = pyOrderAdapter_GetStringFromQueryResult(qresult, 0);
	pyOrderAdapter_FreeQueryResult(qresult);

	return result;
}

std::string spdOrderAPI::QueryFutUncoverRT(const std::map<std::string, std::string>& query_param)
{
	void* qparam = pyOrderAdapter_CreateQueryParam();
	std::map<std::string, std::string>::const_iterator iter = query_param.cbegin();
	for (; iter != query_param.cend(); iter++)
		pyOrderAdapter_AddQueryParam(qparam, iter->first.c_str(), iter->second.c_str());

	void* qresult = pyOrderAdapter_QueryFutUncoverRT(orderAPI, qparam);
	pyOrderAdapter_FreeQueryParam(qparam);
	std::string result = pyOrderAdapter_GetStringFromQueryResult(qresult, 0);
	pyOrderAdapter_FreeQueryResult(qresult);

	return result;
}

std::string spdOrderAPI::QueryMargin(const std::map<std::string, std::string>& query_param)
{
	void* qparam = pyOrderAdapter_CreateQueryParam();
	std::map<std::string, std::string>::const_iterator iter = query_param.cbegin();
	for (; iter != query_param.cend(); iter++)
		pyOrderAdapter_AddQueryParam(qparam, iter->first.c_str(), iter->second.c_str());

	void* qresult = pyOrderAdapter_QueryMargin(orderAPI, qparam);
	pyOrderAdapter_FreeQueryParam(qparam);
	std::string result = pyOrderAdapter_GetStringFromQueryResult(qresult, 0);
	pyOrderAdapter_FreeQueryResult(qresult);

	return result;
}

std::string spdOrderAPI::QueryForeignStockInventory(const std::map<std::string, std::string>& query_param)
{
	void* qparam = pyOrderAdapter_CreateQueryParam();
	std::map<std::string, std::string>::const_iterator iter = query_param.cbegin();
	for (; iter != query_param.cend(); iter++)
		pyOrderAdapter_AddQueryParam(qparam, iter->first.c_str(), iter->second.c_str());

	void* qresult = pyOrderAdapter_QueryForeignStockInventory(orderAPI, qparam);
	pyOrderAdapter_FreeQueryParam(qparam);
	std::string result = pyOrderAdapter_GetStringFromQueryResult(qresult, 0);
	pyOrderAdapter_FreeQueryResult(qresult);

	return result;
}

std::string spdOrderAPI::QueryForeignStockOrder(const std::map<std::string, std::string>& query_param)
{
	void* qparam = pyOrderAdapter_CreateQueryParam();
	std::map<std::string, std::string>::const_iterator iter = query_param.cbegin();
	for (; iter != query_param.cend(); iter++)
		pyOrderAdapter_AddQueryParam(qparam, iter->first.c_str(), iter->second.c_str());

	void* qresult = pyOrderAdapter_QueryForeignStockOrder(orderAPI, qparam);
	pyOrderAdapter_FreeQueryParam(qparam);
	std::string result = pyOrderAdapter_GetStringFromQueryResult(qresult, 0);
	pyOrderAdapter_FreeQueryResult(qresult);

	return result;
}

std::string spdOrderAPI::QueryForeignStockFilled(const std::map<std::string, std::string>& query_param)
{
	void* qparam = pyOrderAdapter_CreateQueryParam();
	std::map<std::string, std::string>::const_iterator iter = query_param.cbegin();
	for (; iter != query_param.cend(); iter++)
		pyOrderAdapter_AddQueryParam(qparam, iter->first.c_str(), iter->second.c_str());

	void* qresult = pyOrderAdapter_QueryForeignStockFilled(orderAPI, qparam);
	pyOrderAdapter_FreeQueryParam(qparam);
	std::string result = pyOrderAdapter_GetStringFromQueryResult(qresult, 0);
	pyOrderAdapter_FreeQueryResult(qresult);

	return result;
}

std::string spdOrderAPI::DownloadForeignStockProductData(const std::map<std::string, std::string>& query_param, const char* gzfname_prefix)
{
	void* qparam = pyOrderAdapter_CreateQueryParam();
	std::map<std::string, std::string>::const_iterator iter = query_param.cbegin();
	for (; iter != query_param.cend(); iter++)
		pyOrderAdapter_AddQueryParam(qparam, iter->first.c_str(), iter->second.c_str());

	void* qresult = pyOrderAdapter_DownloadForeignStockProductData(orderAPI, qparam, gzfname_prefix);
	pyOrderAdapter_FreeQueryParam(qparam);
	std::string result = pyOrderAdapter_GetStringFromQueryResult(qresult, 0);
	pyOrderAdapter_FreeQueryResult(qresult);

	return result;
}

std::string spdOrderAPI::DownloadForeignStockCurrencyData(const std::map<std::string, std::string>& query_param)
{
	void* qparam = pyOrderAdapter_CreateQueryParam();
	std::map<std::string, std::string>::const_iterator iter = query_param.cbegin();
	for (; iter != query_param.cend(); iter++)
		pyOrderAdapter_AddQueryParam(qparam, iter->first.c_str(), iter->second.c_str());

	void* qresult = pyOrderAdapter_DownloadForeignStockCurrencyData(orderAPI, qparam);
	pyOrderAdapter_FreeQueryParam(qparam);
	std::string result = pyOrderAdapter_GetStringFromQueryResult(qresult, 0);
	pyOrderAdapter_FreeQueryResult(qresult);

	return result;
}

std::string spdOrderAPI::DownloadForeignStockMarketData(const std::map<std::string, std::string>& query_param)
{
	void* qparam = pyOrderAdapter_CreateQueryParam();
	std::map<std::string, std::string>::const_iterator iter = query_param.cbegin();
	for (; iter != query_param.cend(); iter++)
		pyOrderAdapter_AddQueryParam(qparam, iter->first.c_str(), iter->second.c_str());

	void* qresult = pyOrderAdapter_DownloadForeignStockMarketData(orderAPI, qparam);
	pyOrderAdapter_FreeQueryParam(qparam);
	std::string result = pyOrderAdapter_GetStringFromQueryResult(qresult, 0);
	pyOrderAdapter_FreeQueryResult(qresult);

	return result;
}

std::string spdOrderAPI::GetMKChartData(const char* symbol)
{
	void* qresult = pyOrderAdapter_GetMKChartData(orderAPI, symbol);
	std::string result = pyOrderAdapter_GetStringFromQueryResult(qresult, 1);
	pyOrderAdapter_FreeQueryResult(qresult);

	return result;
}

std::string spdOrderAPI::GetWKChartData(const char* symbol)
{
	void* qresult = pyOrderAdapter_GetWKChartData(orderAPI, symbol);
	std::string result = pyOrderAdapter_GetStringFromQueryResult(qresult,1);
	pyOrderAdapter_FreeQueryResult(qresult);

	return result;
}

std::string spdOrderAPI::GetDKChartData(const char* symbol)
{
	void* qresult = pyOrderAdapter_GetDKChartData(orderAPI, symbol);
	std::string result = pyOrderAdapter_GetStringFromQueryResult(qresult, 1);
	pyOrderAdapter_FreeQueryResult(qresult);

	return result;
}

std::string spdOrderAPI::GetAdjustedDKChartData(const char* symbol)
{
	void* qresult = pyOrderAdapter_GetAdjustedDKChartData(orderAPI, symbol);
	std::string result = pyOrderAdapter_GetStringFromQueryResult(qresult, 1);
	pyOrderAdapter_FreeQueryResult(qresult);

	return result;
}

std::string spdOrderAPI::GetAdjustedWKChartData(const char* symbol)
{
	void* qresult = pyOrderAdapter_GetAdjustedWKChartData(orderAPI, symbol);
	std::string result = pyOrderAdapter_GetStringFromQueryResult(qresult, 1);
	pyOrderAdapter_FreeQueryResult(qresult);

	return result;
}

std::string spdOrderAPI::GetAdjustedMKChartData(const char* symbol)
{
	void* qresult = pyOrderAdapter_GetAdjustedMKChartData(orderAPI, symbol);
	std::string result = pyOrderAdapter_GetStringFromQueryResult(qresult, 1);
	pyOrderAdapter_FreeQueryResult(qresult);

	return result;
}