支持的券商

TradeApi理论上支持所有券商,但因为券商繁多,我们目前提供了针对同花顺5.0~7.0的代理下单策略,总计支持70~80家券商,下方是支持的部分券商名单(完整券商名单请见:同花顺交易客户端相关->下载):

支持的编程语言

TradeApi Api支持多种编程语言,包括C++、Python、Java、C#、Golang、易语言等 。

支持的操作系统

TradeApi Api支持Windows操作系统,版本要求Windows7、Windows2008及以上。

报单程序窗口和TradeAgent窗口

下图黑色的窗口为通过TradeApi的Api开发的自编程序向TradeAgent.exe进程(本机IP:127.0.0.1)进行报单, 由TradeAgent.exe并统计下单记录和资金曲线。

下单流程图

C++ 下单程序流程图

Python 下单程序流程图

库文件说明

C++ 库文件

TradeApi提供的Api是C++库,理论上可以用于包括C++、Python、Java、C#、等在内的多种编程语言的调用。

TradeApi Api支持Windows操作系统,运行采用TradeApi Api的计算机和TradeAgent.exe的计算机采用要求Windows7、Windows2008及以上系统,并元要求对于Windwo7和Windows Server2008这些较为陈旧的Windows系统安装微软运行时库redist2015补丁。

包含以下文件:

其中ThostFtdcTradeApiDataType.h、ThostFtdcTradeApiStruct.h、ThostFtdcTraderApi.h是头文件,TradeApi.dll 动态库文件、TradeApi.lib。

Python 库文件

Python库是在原来C++ 库基础上增加了TradeApiForPython.dll和TradeApi.py,通过TradeApi.py采用ctypes方式调用 TradeApiForPython.dll 调用原生C++库中的 TradeApi.dll ,不再需要用户在开发过程中使用ThostFtdcTradeApiDataType.h、ThostFtdcTradeApiStruct.h、ThostFtdcTraderApi.h、TradeApi.lib这几个文件。

包含以下文件:

其中TradeApi.py是库文件、TradeApi.dll 是动态库文件、TradeApiForPython.dll 是动态库文件。

C++ Demo

C++ Demo采用Visual Studio2015、Visual Studio2017、Visual Studio2019 编译,运行test.sln打开Demo项目。

微软最新版本的Visual Studio下载: https://visualstudio.microsoft.com/zh-hans/downloads/

test.cpp


#include "stdafx.h"
#include "..\\..\\Library(C++)\\ThostFtdcTradeApiDataType.h"
#include "..\\..\\Library(C++)\\ThostFtdcTradeApiStruct.h"
#include "..\\..\\Library(C++)\\ThostFtdcTraderApi.h"
#include "TraderSpi.h"

CThostFtdcTraderApi *pTdApi;
CTraderSpi* pTdSpi;

#ifdef _WIN64
    #pragma comment(lib, "..\\..\\Library(C++)\\x64\\TradeApi.lib")
#else
    #pragma comment(lib, "..\\..\\Library(C++)\\x86\\TradeApi.lib")
#endif

char  FRONT_ADDR[] = "";		    // 前置地址
TThostFtdcBrokerIDType	BROKER_ID = "";				// 经纪公司代码
TThostFtdcInvestorIDType INVESTOR_ID = "";			// 投资者代码
TThostFtdcPasswordType  PASSWORD = "";			// 用户密码
int iInstrumentID = 1;
char *ppInstrumentID[] = {""};
double runtime = 0;
int iRequestID = 0;
bool usermssql = 0;
DWORD WINAPI GetQry(const LPVOID lpParam)
{

	while (1)
	{
		//查询“资金余额” 在回调函数中返回
		pTdSpi->ReqQryTradingAccount(QRY_ACCOUNT_BALANCE);
 		Sleep(3000);
		//查询“冻结的资金”
		pTdSpi->ReqQryTradingAccount(QRY_ACCOUNT_FROZENCASH);
		Sleep(3000);
		//查询“可用资金”
		pTdSpi->ReqQryTradingAccount(QRY_ACCOUNT_AVAILABLE);
		Sleep(3000);
		//查询“可取资金”
		pTdSpi->ReqQryTradingAccount(QRY_ACCOUNT_WITHDRAWQUOTA);
		Sleep(3000);
		//查询“股票市值”
		pTdSpi->ReqQryTradingAccount(QRY_ACCOUNT_STOCKVALUE);
		Sleep(3000);
		//查询“总资产”
		pTdSpi->ReqQryTradingAccount(QRY_ACCOUNT_TOTAL);
		Sleep(3000);
	}
}
int main()
{
	//TradeApi是A股交易接口
	SYSTEMTIME st = { 0 };
	GetLocalTime(&st);
	runtime = 10000 * st.wYear + 100 * st.wMonth + st.wDay + 0.01*st.wHour + 0.0001*st.wMinute + 0.000001*st.wSecond
	//因为在某些操作系统,例如某些最新版本的Windows10控制台,采用的编码为936,运行多字节会出现乱码,可以运行后设置,也可以运行下面命令直接切换至老式控制台编码
	//若控制台乱码,请将needchcp改为1
	bool needchcp =0;
	if (needchcp) 
	{
		system("chcp 20936");
	}
	cerr << "--->>> " << "Initialing TradeApi(www.tradeapi.cn 交易API库)Demo" << endl;
	pTdApi = CThostFtdcTraderApi::CreateFtdcTraderApi();  // 创建交易
	pTdSpi = new CTraderSpi();
	//设置登录TradeAgent.exe进程服务的用户名和密码,账户密码配置见TradeAgent.exe目录下的setting.ini文件
	pTdApi->SetLoginInfo("wdg", "000000wdg");
	//设置交易参数,以便进行开仓数的计算和资金管理,100万资金,50%仓位,份10只股票买入,那么计算出每只股票使用50000元进行买入
	//对股票最大开仓仓位30000股,如果不设置价格错误比如错误的价格数字1,GetCalOpenVolume(1),会导致一个极大的开仓数,导致潜在风险
	//计算开仓数,请使用pTdApi->GetCalOpenVolume(10)方法进行计算,参数为价格10,50000/10元,即算出5000股
	pTdApi->SetTradeParameters(1000000, 0.5, 10, 30000);
	pTdApi->RegisterSpi(pTdSpi);		 // 注册事件类
	pTdApi->RegisterFront("127.0.0.1");	 // 连接交易服务器
	pTdApi->Init();
	int databasestate = 0;
    //创建查询资金线程
	HANDLE hThread2 = ::CreateThread(NULL, 0, GetQry, NULL, 0, NULL);
	if (!usermssql)
	{
		//运行本程序需要安装Office2007及以上版本里的Access数据库模块,否则因为驱动程序无法顺利运行
		//采用Access方式读取持仓数据,需要指定TradeApi Server的.mdb数据库地址,并在TradeApi Server启用Access数据库方式记录持仓信息
		//pTdApi->InitAccess("..\\..\\TradeData.mdb");
		databasestate = pTdApi->InitAccess("..\\..\\..\\TradeAgent(Server)\\TradeData.mdb");
	}
	else
	{
		//采用MSSQL方式读取持仓数据,需要指定MSSQL数据库地址,并在TradeApi Server启用MSSQL数据库方式记录持仓信息
		databasestate = pTdApi->InitMSSQL("127.0.0.1", "TradeData", "user", "123456Test");
	}
	if (databasestate == 1)
	{
		//通过密码登录,输入正确的密码才能向TradeApi Server提交下单指令,用户名和密码在TraeeApi Server设置
	    pTdSpi->OnRspUserLogin("wdg", "000000wdg");
	    while (1)
	    {
		  //下单测试,买入卖出一个不存在的股票代码,仅供测试
		  //pTdSpi->ReqOrderInsert(1, "800000", pTdApi->GetCalOpenVolume(25.00), 25.00, DIRECTION_BUY);
		  //pTdSpi->ReqOrderInsert(1, "800000", 100, 25.00, DIRECTION_SELL);
		  pTdSpi->ReqOrderInsert(1, "800000", 100, 25, 25, DIRECTION_BUY, "显示在TradeAgent客户端的备注,可用于显示触发信号的变量值等");
		  Sleep(10000);
		  pTdSpi->ReqOrderInsert(1, "800000", 100, 25, 25, DIRECTION_SELL,"显示在TradeAgent客户端的备注,可用于显示触发信号的变量值等");
		  Sleep(10000);
	    }
	}
	return 1;
}
 
	

stdafx.h


// stdafx.h : 标准系统包含文件的包含文件,
// 或是经常使用但不常更改的
// 特定于项目的包含文件
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include "targetver.h"
#include <stdio.h>  
#include <tchar.h>
#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <windows.h>
#include <time.h>
#include <algorithm>
#include <stdlib.h>
using namespace std;
#include <unordered_map>
#include <iostream>
#define DIRECTION_NONE     0
#define DIRECTION_BUY      1
#define DIRECTION_SELL     2

TraderSpi.h


#pragma once
#include "stdafx.h"
#include "..\\..\\Library(C++)\\ThostFtdcTraderApi.h"

class CTraderSpi : public CThostFtdcTraderSpi
{
public:
	///当客户端与交易后台建立起通信连接时(还未登录前),该方法被调用。
	virtual void OnFrontConnected();

	///当客户端与交易后台通信连接断开时,该方法被调用。当发生这个情况后,API会自动重新连接,客户端可不做处理。
	///@param nReason 错误原因
	///        0x1001 网络读失败
	///        0x1002 网络写失败
	///        0x2001 接收心跳超时
	///        0x2002 发送心跳失败
	///        0x2003 收到错误报文
	virtual  void OnFrontDisconnected(int nReason);

	///登录请求响应
	//	virtual  void OnRspUserLogin(CThostFtdcRspUserLoginField *pRspUserLogin, CThostFtdcTradeApiRspInfoField *pRspInfo, int nRequestID, bool bIsLast) ;
	virtual  void OnRspUserLogin(char *username, char *password);

	///登出请求响应
	virtual  void OnRspUserLogout(CThostFtdcTradeApiLogoutField *pUserLogout, CThostFtdcTradeApiRspInfoField *pRspInfo, int nRequestID, bool bIsLast);

	///错误应答
	virtual  void OnRspError(CThostFtdcTradeApiRspInfoField *pRspInfo, int nRequestID, bool bIsLast);

	///报单录入请求响应
	virtual  void OnRspOrderInsert(COrderField *pInputOrder, CThostFtdcTradeApiRspInfoField *pRspInfo, int nRequestID, bool bIsLast);

	///请求查询投资者持仓响应
	virtual  void OnRspQryInvestorPosition(CThostFtdcInvestorPositionField *pInvestorPosition, CThostFtdcTradeApiRspInfoField *pRspInfo, int nRequestID, bool bIsLast);

	virtual  void OnRtnOrder(CThostFtdcTradeOrderField *pOrder);

public:
	///请求查询资金账户
	void ReqQryTradingAccount();

	///请求查询投资者持仓
	void ReqQryInvestorPosition();

	///报单录入请求
	void ReqOrderInsert(int Sid, char *Instrument, int Volume, double Price, double LastPrice, int Direction, char *Remark);

	///报单操作请求
	void ReqOrderAction(CThostFtdcTradeOrderField *pOrder);

};

TraderSpi.cpp


#include 
#include 
#include 
#include 
using namespace std;
#include "stdafx.h"
#include "..\\..\\Library(C++)\\ThostFtdcTraderApi.h"
#include "TraderSpi.h"

#pragma warning(disable : 4996)

// USER_API参数
extern CThostFtdcTraderApi* pTdApi;

// 配置参数
extern char FRONT_ADDR[];		// 前置地址
extern char BROKER_ID[];		// 经纪公司代码
extern char INVESTOR_ID[];		// 投资者代码
extern char PASSWORD[];			// 用户密码
extern char* ppInstrumentID[];
extern int iInstrumentID;
extern char INSTRUMENT_ID[];	// 合约代码
extern TThostFtdcDirectionType	DIRECTION;	// 买卖方向
extern TThostFtdcOffsetFlagType MARKETState;//开平仓
extern TThostFtdcPriceType	LIMIT_PRICE;	// 价格
#define TYPE_NUM 20
extern	double	Q_UpperLimit;
extern	double	Q_LowerLimit;

extern	bool	JustRun;		//正在启动标志

								// 会话参数
TThostFtdcFrontIDType	FRONT_ID;	//前置编号
TThostFtdcSessionIDType	SESSION_ID;	//会话编号
TThostFtdcOrderRefType	ORDER_REF;	//报单引用

extern int needstate;
void CTraderSpi::OnFrontConnected()
{
	cerr << "--->>> " << __FUNCTION__ << endl;
	char username[51] = { 0 };
	char password[51] = { 0 };
	pTdApi->GetLoginInfoUsername(username);
	pTdApi->GetLoginInfoPassword(password);
	pTdApi->ReqUserLogin(username, password);
	printf("[%s] are logging into the TradeAgent server...\n", username);
	///用户登录请求
	//ReqUserLogin();
	Sleep(500);
}
 
void CTraderSpi::OnRspUserLogin(char *username, char *password)
{
	cerr << "--->>> " << __FUNCTION__ << endl;

	/*
	if (pRspUserLogin == NULL)
	{
	cout << "--->>>指针错误OnRspUserLogin" << endl;			  //指针检查
	//WirteTradeRecordToFileMainThread(0, "OnRspUserLogin指针错误");
	Sleep(5000);
	ReqUserLogin();// 自己添加
	return;
	}

	if (IsErrorRspInfo(pRspInfo))
	{
	cerr << "--->>> 交易登录错误: " << pRspInfo->ErrorID << pRspInfo->ErrorMsg << endl;
	//WirteTradeRecordToFileMainThread(0, "交易登录错误");

	Sleep(5000);
	ReqUserLogin();// 自己添加

	}

	if (bIsLast && !IsErrorRspInfo(pRspInfo))
	{
	// 保存会话参数
	FRONT_ID = pRspUserLogin->FrontID;
	SESSION_ID = pRspUserLogin->SessionID;
	int iNextOrderRef = atoi(pRspUserLogin->MaxOrderRef);
	iNextOrderRef++;
	sprintf(ORDER_REF, "%d", iNextOrderRef);
	//cerr << "--->>> 报单引用 = " << ORDER_REF << endl;
	///获取当前交易日

	char TradingDay[9] = { "0" };
	strcpy(TradingDay, pTdApi->GetTradingDay());
	cerr << "--->>> 获取当前交易日 = " << pTdApi->GetTradingDay() << endl;

	}
	*/
}


void CTraderSpi::OnRspUserLogout(CThostFtdcTradeApiLogoutField *pUserLogout, CThostFtdcTradeApiRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
}




extern  double YestayAllAmount;
extern  double TodayAllAmount;
//extern  double UserAmount;

int  JsReqQryTradingAccountFailer = 0;
void CTraderSpi::ReqQryTradingAccount()
{
	/*
	CThostFtdcQryTradingAccountField req;
	memset(&req, 0, sizeof(req));
	strcpy(req.BrokerID, BROKER_ID);
	strcpy(req.InvestorID, INVESTOR_ID);
	int iResult = pTdApi->ReqQryTradingAccount(&req, ++iRequestID);
	//cerr << "--->>> 请求查询资金账户: " << ((iResult == 0) ? "成功" : "失败") << endl;


	if (iResult == 0)
	{
	JsReqQryTradingAccountFailer=  0;
	}
	else
	{
	JsReqQryTradingAccountFailer++;
	if (JsReqQryTradingAccountFailer > 20)
	{
	printf("请求查询资金账户资金X失败");
	}
	}
	*/

}

double UserAmount = 0;


void CTraderSpi::ReqQryInvestorPosition()
{
	/*
	CThostFtdcQryInvestorPositionField req;
	memset(&req, 0, sizeof(req));
	strcpy(req.BrokerID, BROKER_ID);
	strcpy(req.InvestorID, INVESTOR_ID);
	strcpy(req.InstrumentID, InstrumentID_n[0]);
	int iResult = pTdApi->ReqQryInvestorPosition(&req, ++iRequestID);
	//cerr << "--->>> 请求查询投资者持仓: " << ((iResult == 0) ? "成功" : "失败") << endl;

	if (iResult == 0)
	{
	JsReqQryInvestorPositionFailer=0;
	}
	else
	{
	JsReqQryInvestorPositionFailer++;
	if (JsReqQryInvestorPositionFailer > 20)
	{
	printf("请求查询投资者持仓X失败");
	}
	}
	*/

}







bool FindStr(int id, char * str)
{

	//char * pdest1 = strstr(InstrumentID_n[id], str);
	//int  result1 = pdest1 - InstrumentID_n[id] + 1;
	//printf("%s  %s\n", InstrumentID_n[id], str);

	//if (stricmp(InstrumentID_n[id], str) == 0)
	//if (pdest1 != NULL)
	//{	//printf("在%s发现%s\n", InstrumentID_n[id],str );
	return true;
	//}
	//else
	//{
	//printf("%s 没有在%s发现\n", str, InstrumentID_n[id]);
	//	return false;
	//}
}

int SaveInstrumentID = { 0 };
bool  checkstate = false;
bool  TypeCheckState_B_Today[TYPE_NUM] = { false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false };
bool  TypeCheckState_S_Today[TYPE_NUM] = { false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false };

bool  TypeCheckState_B_History[TYPE_NUM] = { false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false };
bool  TypeCheckState_S_History[TYPE_NUM] = { false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false };

int	Trade_dataA_Amount_S_History[TYPE_NUM] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };		//空头持仓
int	Trade_dataA_Amount_S_Today[TYPE_NUM] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };		//空头持仓


int	Trade_dataA_Amount_B_History[TYPE_NUM] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };		//多头持仓
int	Trade_dataA_Amount_B_Today[TYPE_NUM] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };		//多头持仓

																												//int	Trade_dataA_Amount_B_Today = 0;		//多头持仓
																												//int	Trade_dataA_Amount_S_Today = 0;		//多头持仓

bool orderstate = false;


 

///请求查询投资者持仓响应
void CTraderSpi::OnRspQryInvestorPosition(CThostFtdcInvestorPositionField *pInvestorPosition, CThostFtdcTradeApiRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{

}

 
extern  int iRequestID;
extern int  MAX_TRADENUM;
extern double totlemoney;

 
void CTraderSpi::ReqOrderInsert(int Sid, char *Instrument, int Volume, double Price, double LastPrice, int Direction, char *Remark)
{
	COrderField req;
	memset(&req, 0, sizeof(req));
	req.Sid = Sid;                        //策略ID编号
	strcpy(req.InstrumentID, Instrument); //股票代码
	_snprintf_s(req.Remark, sizeof(req.Remark), sizeof(req.Remark) - 1, "%s", Remark); //备注,也可以输出策略程序的变量等

	req.Volume = Volume;                     //下单数量
	req.Price = Price;                    //委托价格
	req.LastPrice = LastPrice;                    //委托价格

	req.Direction = Direction;            //买卖方向
	int iRequestID = 1;
	int iResult = pTdApi->ReqOrderInsert(&req, ++iRequestID);
	cerr << "--->>> 报单录入请求: " << ((iResult == 0) ? "成功" : "失败") << endl;
}

void CTraderSpi::ReqOrderAction(CThostFtdcTradeOrderField *pOrder)
{


}



void CTraderSpi::OnRspOrderInsert(COrderField *pInputOrder, CThostFtdcTradeApiRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
	cerr << "--->>> " << __FUNCTION__ << endl;

	SYSTEMTIME sys_time;
	GetLocalTime(&sys_time);
	double system_times;
	system_times = (double)((sys_time.wHour) / 10e1) + (double)((sys_time.wMinute) / 10e3) + (double)((sys_time.wSecond) / 10e5);	//格式时间0.145100

    //cerr << "--->>> 报单: " <>> " << __FUNCTION__ << endl;
	if (IsMyOrder(pOrder))
	{
		if (IsTradingOrder(pOrder))
			ReqOrderAction(pOrder);
		else if (pOrder->OrderStatus == THOST_FTDC_OST_Canceled)
			cout << "--->>> 撤单成功" << endl;
	}
}

void CTraderSpi::OnFrontDisconnected(int nReason)
{
	cerr << "--->>> " << "OnFrontDisconnected" << endl;
	cerr << "--->>> Reason = " << nReason << endl;
}

void CTraderSpi::OnRspError(CThostFtdcTradeApiRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
	cerr << "--->>> " << "OnRspError" << endl;
	IsErrorRspInfo(pRspInfo);
}

bool CTraderSpi::IsErrorRspInfo(CThostFtdcTradeApiRspInfoField *pRspInfo)
{
	// 如果ErrorID != 0, 说明收到了错误的响应
	bool bResult = ((pRspInfo) && (pRspInfo->ErrorID != 0));
	if (bResult)
		cerr << "--->>> ErrorID=" << pRspInfo->ErrorID << ", ErrorMsg=" << pRspInfo->ErrorMsg << endl;
	return bResult;
}


void CTraderSpi::ReqQryTradingAccount(int Cx)
{
    cerr << "--->>> " << __FUNCTION__ << endl;
    CThostFtdcQryTradingAccountField tn;
    memset(&tn,0,sizeof(CThostFtdcQryTradingAccountField));
    strcpy(tn.InvestorID,"000000");
    int iResult = pTdApi->ReqQryTradingAccount(&tn, Cx);

}

void CTraderSpi::ReqQryInvestorPosition()
{
cerr << "--->>> " << __FUNCTION__ << endl;
}

Python Demo

Demo.py


	
#导入数据库代理
from TradeApi import *
import time, datetime
td = TradeApi()
 

# Direction or bsflag
DIRECTION_NONE           = 0	# 不交易
DIRECTION_BUY 		 = 1	# 买
DIRECTION_SELL 		 = 2	# 卖

def main():
    
    #初始化TradeApi交易库
    td.InitTraderApi()
    #向该IP的TradeAgent.exe进程报单,每个Python实例只能对1个TradeAgent.exe进程报单
    td.RegisterFront("127.0.0.1")
    #设定报单登录密码,错误将无法对TradeAgen.exe进程下单
    #密码应在TradeAgent.exe设置    
    td.SetLoginInfo("wdg", "000000wdg")
    #数据库主要用来记录持仓成本和计算各个策略的资金管理、统计各策略的盈亏曲线和胜率曲线    
    if True:
        #Access数据库需要在运行TradeAgent.exe进程的主机上安装Office2007、Office2013、Office2016的Access模块
        #对32位TradeAgent 32位程序请安装32位的Office(Access),对64位的TradeAgent 64位程序请安装64位的Office(Access)
        #初始化Access数据库,采用Access查询持仓数据,需要指定Access文件路径
        #Access数据库适合运行策略的系统,直接运行TradeAgent.exe下单程序
        #1个策略或多个策略对应本机的1个TradeAgent.exe进程,对1个证券账户进行交易,数据库文件TradeData.mdb在TradeAgent.exe目录下
        td.InitAccess("..\\..\\..\\TradeAgent(Server)\\TradeData2.mdb")
    else:
        #MSSQL数据库需要在运行TradeAgent.exe进程的主机上安装MSSQL,并导入TradeData.mdb到MSSQL,
        #并配置管理器设置IP启用的地址断和数据库账户访问权限和密码
        #初始化MSSQL数据库,采用MSSQL查询持仓数据,需要指定MSSQL网络连接方式
        #MSSQL数据库适合运行策略的提交到多个账户交易的TradeAgent.exe系统
        #1个策略或多个策略对应网络(物理主机或虚拟机)多个TradeAgent.exe进程,对多个证券账户进行交易,
        #MSSQL数据库安装在运行TradeAgent.exe物理主机或虚拟机上
        td.InitMSSQL("127.0.0.1","username","password")
    while(1):
        #下单测试,买入卖出一个不存在的股票代码,仅供测试
        #td.ReqOrderInsert(1, "800000", pTdApi->GetCalOpenVolume(25.00), 25.00, DIRECTION_BUY);
        #td.ReqOrderInsert(1, "800000", 100, 25.00, DIRECTION_SELL);
        print(u"下单测试[买入]")
        td.ReqOrderInsert(1, "800000", 100, 25, 25, DIRECTION_BUY, U"显示在TradeAgent客户端的备注,可用于显示触发信号的变量值等")
        time.sleep(10)
        print(u"下单测试[卖出]")
        td.ReqOrderInsert(1, "800000", 100, 25, 25, DIRECTION_SELL,U"显示在TradeAgent客户端的备注,可用于显示触发信号的变量值等")
        time.sleep(10)    

if __name__ == '__main__':
    main()
	

C++ 库提供的方法

以下是C++ 库头文件中提供并列出方法:


/////////////////////////////////////////////////////////////////////////
///@system TradeApi
///@file ThostFtdcTraderApi.h
///@brief 定义了客户端接口
///@history 
///20190301		创建该文件
/////////////////////////////////////////////////////////////////////////

#if !defined(THOST_FTDCTRADERAPI_H)
#define THOST_FTDCTRADERAPI_H

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "ThostFtdcTradeApiStruct.h"

#if defined(ISLIB) && defined(WIN32)
#ifdef LIB_TRADER_API_EXPORT
#define TRADER_API_EXPORT __declspec(dllexport)
#else
#define TRADER_API_EXPORT __declspec(dllimport)
#endif
#else
#define TRADER_API_EXPORT 
#endif

class CThostFtdcTraderSpi
{
public:
	///当客户端与交易后台建立起通信连接时(还未登录前),该方法被调用。
	virtual void OnFrontConnected() {};

	///当客户端与交易后台通信连接断开时,该方法被调用。当发生这个情况后,API会自动重新连接,客户端可不做处理。
	///@param nReason 错误原因
	///        0x1001 网络读失败
	///        0x1002 网络写失败
	///        0x2001 接收心跳超时
	///        0x2002 发送心跳失败
	///        0x2003 收到错误报文
	virtual void OnFrontDisconnected(int nReason) {};

	///登录请求响应
	//virtual void OnRspUserLogin(CThostFtdcRspUserLoginField *pRspUserLogin, CThostFtdcTradeApiRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {};
	virtual void OnRspUserLogin(char *username,char *password) {};

	///登出请求响应
	virtual void OnRspUserLogout(CThostFtdcTradeApiLogoutField *pUserLogout, CThostFtdcTradeApiRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {};

	///错误应答
	virtual void OnRspError(CThostFtdcTradeApiRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {};

	///报单录入请求响应
	virtual void OnRspOrderInsert(COrderField *pInputOrder, CThostFtdcTradeApiRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {};

	///请求查询投资者持仓响应
	virtual void OnRspQryInvestorPosition(CThostFtdcInvestorPositionField *pInvestorPosition, CThostFtdcTradeApiRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {};

	///请求查询隔日监控的股票响应
	virtual void OnRspQryMonitor(CMonitorField *pInputOrder) {};

	virtual void OnRtnOrder(CThostFtdcTradeOrderField *pOrder) {};

};

class TRADER_API_EXPORT CThostFtdcTraderApi
{
public:
	///创建TraderApi
	///@param pszFlowPath 存贮订阅信息文件的目录,默认为当前目录
	///@return 创建出的UserApi
	static CThostFtdcTraderApi *CreateFtdcTraderApi(const char *pszFlowPath = "", const bool bIsUsingUdp = false, const bool bIsMulticast = false);

	///获取API的版本信息
	///@retrun 获取到的版本号
	static const char *GetApiVersion();

	///删除接口对象本身
	///@remark 不再使用本接口对象时,调用该函数删除接口对象
	virtual void Release() = 0;

	///初始化
	///@remark 初始化运行环境,只有调用后,接口才开始工作
	virtual void Init() = 0;

	///获取当前交易日
	///@retrun 获取到的交易日
	///@remark 只有登录成功后,才能得到正确的交易日
	virtual const char *GetTradingDay() = 0;

	///注册前置机网络地址
	///@param pszFrontAddress:前置机网络地址。
	///@remark 网络地址的格式为:“protocol://ipaddress:port”,如:”tcp://127.0.0.1:17001”。 
	///@remark “tcp”代表传输协议,“127.0.0.1”代表服务器地址。”17001”代表服务器端口号。
	virtual void RegisterFront(char *pszFrontAddress) = 0;

	///注册回调接口
	///@param pSpi 派生自回调接口类的实例
	virtual void RegisterSpi(CThostFtdcTraderSpi *pSpi) = 0;
 
	///用户登录请求
	virtual int ReqUserLogin(char *username, char *password) = 0;

	///登出请求
	virtual int ReqUserLogout(CThostFtdcTradeApiLogoutField *pUserLogout, int nRequestID) = 0;

	///报单录入请求
	///@param pInputOrder  报单信息
	virtual int ReqOrderInsert(COrderField *pInputOrder, int nRequestID) = 0;

	///设置API登录TradeAgent账户和密码,需要在TradeAgent.exe目录下的setting.ini中配置的一致,否则TradeAgent.exe无法接收下单指令
	///@param username  账户
	///@param password  密码
	virtual void SetLoginInfo(char * Username, char *Password) = 0;

	///获取根据SetLoginInfo设置的账户
	///@param username  返回账户
	virtual void GetLoginInfoUsername(char * Username) = 0;

	///获取根据SetLoginInfo设置的密码
	///@param username  返回账户
	virtual void GetLoginInfoPassword(char * Password) = 0;

	///设置交易参数
	///@param useramount  账户资金总额
	///@param positonrate 仓位比例
	///@param number      分成几份购买股票,即购买股票数量   
	///购买每只股票的金额应该为 useramount*positonrate/number
	///若购买number只股票一共占用positonrate的仓位
	virtual void SetTradeParameters(double Useramount, double Positonrate,int StockNum,int Maxvol) = 0;

	///读取交易参数
	///@param useramount  账户资金总额
	///@param positonrate 仓位比例
	///@param number      分成几份购买股票,即购买股票数量   
	///返回值表示是否已经设置了交易参数,参数值存储在数据库的setting表里
	virtual bool GetTradeParameters() = 0;

	///读取交易参数
	///@param useramount  账户资金总额
	///@param positonrate 仓位比例
	///@param number      分成几份购买股票,即购买股票数量   
	///返回值表示是否已经设置了交易参数,参数值存储在数据库的setting表里,并返回设置的值
	virtual bool GetTradeParameters(double * Useramount, double * Positonrate, int * StockNum, int * Maxvol) = 0;

	///根据SetTradeParameters设置的参数和价格来计算股票开仓手数
	///@param Price  价格
	virtual int GetCalOpenVolume(double Price) = 0;

	///初始化MSSQL数据库,采用MSSQL查询持仓数据
	///@param databaseaddress MSSQL数据库地址
	///@param datasource  数据库名称
	///@param username  数据库用户名
	///@param password  数据库密码
	virtual int InitMSSQL(char * databaseaddress, char *datasource, char * username, char * password) = 0;

	///初始化Access数据库,采用Access查询持仓数据,需要指定Access文件路径
	///@param path  Access数据库文件路径,一般用于本机 
	virtual int InitAccess(char *path) = 0;

	///设置Sid策略占用的总资金限额
	///@param Sid  策略编号 
	virtual int SetAmount(int Sid, double AmountLimit) = 0;

	///获得Sid策略可使用的剩余金额AmountLeft  = 总资金限额AmountLimit -当前使用的
	///@param Sid  策略编号 
	virtual double GetAmount(int Sid) = 0;

	///获得股票合约代码可使用的剩余金额
	///@param InstrumentID  股票合约代码 
	virtual double GetAmount(char * InstrumentID) = 0;

	///获得股票合约代码可使用的剩余数量
	///@param InstrumentID  股票合约代码 
	virtual int GetVolume(char * InstrumentID) = 0;

	///查询所有股票合约持仓,来源下单代理软件数据库并非从券商账户查询,因为按涨停板价格下单购买就认为已经成交
	///@param Instrument 股票合约代码  
	///@param sid 策略ID  
	///@param diffday 查询日期间隔大于diffday的持仓
	//virtual int ReqDatabasePosition(char *InstrumentID, int Sid, int Diffday, int Direction) = 0;

	///从MSSQL或Access数据库读取某一Sid的策略占用的资金占总资金比例,使用本方法前,需要执行InitMSSQL或InitAccess方法
	///来源下单代理软件数据库并非从券商账户查询,因为按涨停板价格下单购买就认为已经成交
	///@param sid 策略编号
	///@param diffday 查询日期间隔大于diffday的持仓
	virtual int RealtimeReadFromDatabaseInvestmentproportion(char *InstrumentID, int Sid, int Diffday, int Direction)=0;

	///从MSSQL或Access数据库读取某一Sid的策略占用的资金数,使用本方法前,需要执行InitMSSQL或InitAccess方法
	///来源下单代理软件数据库并非从券商账户查询,因为按涨停板价格下单购买就认为已经成交
	///@param sid 策略编号 
	///@param diffday 查询日期间隔大于diffday的持仓
	virtual int RealtimeReadFromDatabasePosition(char *InstrumentID, int Sid, int Diffday, int Direction) = 0;

	///从MSSQL或Access数据库读取合约持仓股票数量,使用本方法前,需要执行InitMSSQL或InitAccess方法
	///来源下单代理软件数据库并非从券商账户查询,因为按涨停板价格下单购买就认为已经成交
	///@param InstrumentID     股票合约代码
	///@param Sid              策略编号
	///@param Diffday          查询日期间隔大于Diffday的持仓
	///@param Direction        方向
	virtual int RealtimeReadFromDatabaseVolume(char *InstrumentID, int Sid, int Diffday, int Direction) = 0;

	///从MSSQL或Access数据库读取合约持仓股票数量,使用本方法前,需要执行InitMSSQL或InitAccess方法
	///来源下单代理软件数据库并非从券商账户查询,因为按涨停板价格下单购买就认为已经成交
	///@param InstrumentID     股票合约代码
	///@param Sid              策略编号
	///@param Direction        方向
	virtual int RealtimeReadFromDatabaseGetBuyPosition(char *InstrumentID,int Sid, int Diffday, int Direction) = 0;

	///从MSSQL或Access数据库读取股票持仓成本价,使用本方法前,需要执行InitMSSQL或InitAccess方法
	///@param InstrumentID     股票合约代码
	///@param Sid              策略编号
	virtual double RealtimeReadFromDatabaseGetCostPrice(char *InstrumentID, int Sid) = 0;

	///从MSSQL或Access数据库读取购买成交之后的日期,使用本方法前,需要执行InitMSSQL或InitAccess方法
	///@param InstrumentID     股票合约代码
	///@param Sid              策略编号
	virtual int RealtimeReadFromDatabaseGetBuyDate(char *InstrumentID, int Sid) = 0;

	///读取止盈或止损的记录信息
	///@param InstrumentID     股票合约代码
	///@param Sid              策略编号
	///@param Type             止盈止损
	///@param Price            触发价格
	virtual double RealtimeReadFromDatabaseGetMonitor(char *InstrumentID, int Sid, int Type, double Price) = 0;


protected:
	~CThostFtdcTraderApi() {};
};

#endif

  

Python 库提供的方法

Python库提供和C++库相同名称的方法

	

# -*- coding=utf-8 -*-
from ctypes import *
 
class TradeApi(object):
	def __init__(self):
		self.dll = CDLL('TradeApiForPython.dll')
		
		self.fInitTraderApi = self.dll.InitTraderApi
		self.fInitTraderApi.argtypes = []
		self.fInitTraderApi.restype = c_void_p
		
		self.fRegisterFront = self.dll.RegisterFront
		self.fRegisterFront.argtypes = [c_char_p]
		self.fRegisterFront.restype = c_void_p			
		
		
		self.fSetLoginInfo = self.dll.SetLoginInfo
		self.fSetLoginInfo.argtypes = [c_char_p,c_char_p]
		self.fSetLoginInfo.restype = c_void_p		
 		
		self.fSetTradeParameters = self.dll.SetTradeParameters
		self.fSetTradeParameters.argtypes = [c_double,c_double,c_int,c_int]
		self.fSetTradeParameters.restype = c_void_p	 		
 		
		self.fInitAccess = self.dll.InitAccess
		self.fInitAccess.argtypes = [c_char_p]
		self.fInitAccess.restype = c_void_p
		
		self.fInitMSSQL = self.dll.InitMSSQL
		self.fInitMSSQL.argtypes = [c_char_p,c_char_p,c_char_p,c_char_p]
		self.fInitMSSQL.restype = c_void_p		
		
		
		self.fReqOrderInsert = self.dll.ReqOrderInsert
		self.fReqOrderInsert.argtypes = [c_int,c_char_p,c_int,c_double,c_double,c_int,c_char_p]
		self.fReqOrderInsert.restype = c_void_p
		
		self.fSetAmount = self.dll.SetAmount
		self.fSetAmount.argtypes = [c_int, c_double]
		self.fSetAmount.restype = c_void_p		
		
		self.fGetAmount = self.dll.GetAmount
		self.fGetAmount.argtypes = [c_int]
		self.fGetAmount.restype = c_double		
  		
		
	#取该股最后一次更新的数据
	#def GetStockData(self,InstrumentID,tid):
	#	return self.fGetStockData(InstrumentID,tid)
	
	#按时间先后顺序获取采集的TICK数据;每取一此数据,则从缓冲区删除该数据;
	#如果长时间不取数据,为防止内存不断这家而溢出,则缓冲队列只保留最近的3万个
	#def GetLastTick(self,InstrumentID,tid):
	#	return self.fGetLastTick(InstrumentID,tid)	
	
	#登录TradeAgent.exe进程的账户和密码,以保证交易指令确实是自己的策略进程发出
	def InitTraderApi(self):
		return self.fInitTraderApi()
	
	#向该IP的TradeAgent.exe进程报单,每个Python实例只能对1个TradeAgent.exe进程报单
	def RegisterFront(self,ip):
		return self.fRegisterFront(ip)
	
	#设定报单登录密码,错误将无法对TradeAgen.exe进程下单
	#密码应在TradeAgent.exe设置
	def SetLoginInfo(self,name,password):
		return self.fSetLoginInfo(name,password)
	
	#设置交易参数,以便进行开仓数的计算和资金管理,100万资金,50%仓位,份10只股票买入,那么计算出每只股票使用50000元进行买入
	#对股票最大开仓仓位30000股,如果不设置价格错误比如错误的价格数字1,GetCalOpenVolume(1),会导致一个极大的开仓数,导致潜在风险
	#计算开仓数,请使用pTdApi->GetCalOpenVolume(10)方法进行计算,参数为价格10,50000/10元,即算出5000股
 	#@param useramount  账户资金总额
	#@param positonrate 仓位比例
	#@param number      分成几份购买股票,即购买股票数量   
	#购买每只股票的金额应该为 useramount*positonrate/number
	#若购买number只股票一共占用positonrate的仓位	
	def SetTradeParameters(self, Useramount, Positonrate, Number, Maxvol):
		return self.fSetTradeParameters(Useramount, Positonrate, Number, Maxvol)
	
	#初始化Access数据库,采用Access查询持仓数据,需要指定Access文件路径
	#@param path  Access数据库文件路径,一般用于本机 
	def InitAccess(self, path):
		return self.fInitAccess(path)
	
	#初始化MSSQL数据库,采用MSSQL查询持仓数据,需要指定MSSQL网络路径
	#@param path  Access数据库文件路径,一般用于本机 
	def InitMSSQL(self, ip, datasource, username, password):
		return self.fInitMSSQL(ip, ip, datasource, username, password)	
		
	#报单录入请求
	#@param Sid         策略编号
	#@param Instrument  股票或合约代码
	#@param Volume      下单量(手)
	#@param Price       下单价格
	#@param LastPrice   当前价格(用于TradeAge 计算统计盈亏成本)
	#@param Direction   买卖方向
	#@param Remark      备注(可在 TradeAge 显示策略变量的值)
	def ReqOrderInsert(self, Sid, Instrument, Volume, Price, LastPrice, Direction, Remark):
		return self.fReqOrderInsert( Sid, Instrument, Volume, Price, LastPrice, Direction, Remark)
	
	#设置Sid策略占用的总资金限额
	#@param Sid  策略编号 
	def SetAmount(self, Sid, AmountLimit):
		return self.fSetAmount(Sid, AmountLimit)	
	 
	#获得Sid策略可使用的剩余金额AmountLeft  = 总资金限额AmountLimit -当前使用的
	#@param Sid  策略编号 
	def GetAmount(self, Sid,):
		return self.fGetAmount(Sid)	
	

TradeAgent.exe进程窗口如下图:

自带策略资金管理,仓位自动计算、方便管理多个策略各自持仓和盈亏统计 。

资金管理提供以下功能:

  • 提供了方法可以查询各个策略的持仓;
  • 对各个策略进行了平均盈亏,交易次数,胜率的统计;
  • 支持自动禁用不盈利的策略;
  • 支持策略收益曲线图;
  • 支持人工设置策略模式,列入牛市模式,熊市模式。

多维度策略管理,自带多策略盈亏统计,自动淘汰策略, 全面的资金管理功能,有效降低开发成本。例如:

C++ 下单方法:

///报单录入请求
///@param Sid         策略编号
///@param Instrument  股票代码
///@param Volume      成交量
///@param Price       价格
///@param LastPrice   最新价(用于统计成本)
///@param Direction   交易方向(买、卖)
///@param Remark      备注(用于在TradeAgent进程窗口显示该笔交易的备注,可用于输出变量值)

void ReqOrderInsert(int Sid, char *Instrument, int Volume, double Price, double LastPrice, int Direction, char *Remark);

C++ 方法调用举例:


pTdSpi->ReqOrderInsert(1, "600000", 100, 25, 25, DIRECTION_BUY, "显示在TradeAgent客户端的备注,可用于显示触发信号的变量值等");

Python 下单方法

td.ReqOrderInsert(1, "600000", 100, 25, 25, DIRECTION_BUY, U"显示在TradeAgent客户端的备注,可用于显示触发信号的变量值等")

策略收益曲线图

策略资金曲线图是在TradeAgent.exe程序中提供的,TradeAgent.exe作为服务器端接收TradeAgent的下单指令,同计算所有策略的收益曲线、盈亏曲线等,不仅提供了曲线图表,还提供多日累计列表方式显示。

双击列表中的一行,打开该记录周期的动态变化曲线

支持自动禁用不盈利的策略

支持自动禁用不盈利的策略

勾选:菜单->设置->自动禁用不盈利的策略

该功能在2.8及以后的版本开启。

人工设置策略模式

对于A股而言,由于牛市和熊市差别很大,所以如果能够认人为设定选择哪些策略进行交易,会更好的使得程交易策略更适合当前行情,获得更好的收益 。TradeApi的配套程序TradeAgent.exe 提供了人工设置策略模式的功能。

本功能在2.8以后的版本提供支持

数据库在TradeApi中的作用

TradeAgent.exe使用数据库保存和读取配置信息和交易记录,并将这些数据用于策略盈亏统计之用。 同时策略程序也需要查询TradeAgent.exe进程下单和策略持仓信息,所以数据库也作为策略程序和TradeAgent.exe进程数据共享只用。

TradeApi同时支持Access和MSSQL这2种数据库。

Access数据库是文件数据库,MSSQL是网络数据库, 如果策略程序和TradeAgent交易代理程序运行在同一个Windows操作系统下,则推荐使用Access数据库,这时Access数据库会比MSSQL更快。

如果策略程序和TradeAgent交易代理程序运行不在同一个Windows操作系统下,则推荐使用MSSQL数据库,如果通过了ftp方式或局域网等方式共享了Access数据库则也可以。

TradeAgent.exe同时支持Access数据库和MSSQL数据库。 运行TradeAgent后默认使用的是Access数据库,可以在菜单选择改用MSSQL数据库重启程序后生效,并在TradeAgent.exe目录下释放出MSSQL.ini,人工修改该配置文件设置MSSQL的登录信息。

选用Access数据库方案

Access是由微软发布的关系数据库管理系统。Access和Word、Excell一样,也是 Microsoft Office 的系统程序之一。

TradeApi的Access数据库环境,需要安装Office2007及以后版本的Access模块,包括Office2007、Office2010、Office2013、Office2016等版本。

对于32位的TradeAgent.exe,需要安装32位版本的Office Access模块。

对于64位的TradeAgent.exe,需要安装64位版本的Office Access模块。

什么情况下需Access数据库?

如果您希望采用TradeApi api的策略程序和交易代理程序TradeAgent.exe以及证券客户端运行在同一个Windows系统下,则可以使用Access数据库。这个模式下,您的策略程序只能向本机的TradeAgente.exe进程报单,只能交易1个证券账户。

选用MSSQL数据库方案

MSSQL是微软发布的大型网络关系型数据库,目前提供的数据库文件版本兼容MSSQL2012及以上版本(MSSQL2012、MSSQL2014、MSSQL2016、MSSQL2017等)。

MSSQL微软官网下载:https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads

最新版本提供了更多的特性,意味着可能对机器配置要求较高,我们并不推荐安装最新的版本,在满足提供安全补丁服务的情况下,选用较低版本MSSQL即可满足要求。

什么情况下需要用MSSQL数据库?

如果您希望采用TradeApi api的策略程序和交易代理程序TradeAgent.exe以及证券客户端运行在不同Windows系统下,则可以使用MSSQL数据库。这个模式下,您的策略程序可以通过API建立多个实例,每个实例绑定一个IP地址,策略程序信号出现后可以向本机的TradeAgente.exe进程报单,可以同时交易多个证券账户。

Access转MSSQL数据库

当您使用Access数据库方案有一段时间后,在TradeData.mdb数据库文件中存有历史交易信息,您希望升级到MSSQL方案并继续使用Access数据库的数据时,可以在MSSQL管理器中导入Access数据库文件TradeData.mdb。

按下面步骤完成转换到MSSQL数据库后,除了需要设置相应权限外,还需将MSSQL的各个数据表的ID字段设置为主键和自增的数据格式。

步骤如下:

下载

同花顺看盘软件图标 ,但这不是我们需要针对各个券商的同花顺交易客户端

同花顺交易客户端是同花顺公司根据各个券商封装的交易客户端,一般有2个渠道可以获得

  • 1. 券商官网下载绿色版的同花顺交易客户端 http://download.10jqka.com.cn/
  • 2.从同花顺官网下载的同花顺客户端安装后,从同花顺看盘软件菜单下载各个券商的绿色版交易软件,一般保存在C盘的目录下,可以复制出来独立运行。 打开同花顺看盘软件的菜单->委托开户->委托管理 打开下面的窗口,选择你需要的券商进行下载交易客户端软件,下载完毕一般在C盘,可拷贝出单独使用。

设置

目前支持同花顺5.0~同花顺7.0 的程序化交易下单,需要关闭同花顺的下单确认功能