CTP JAVA API(JCTP) 64位 2in1及CTP JAVA订阅全市场行情DEMO

12 篇文章 0 订阅
10 篇文章 5 订阅

前言

前面文章将traderapi和mdapi分开来打包,这样就会有两个jar包,里面有些结构体是完全重复的,给一些人造成困惑。其实分开打包的目的主要是方便需要单独用的人,有的人只想接交易,有的人只想接行情。这里根据别人编译的经验,给出一个合并在一起打包的方案,并且给了一个订阅全市场合约行情的demo,大家共同探讨。全部的代码及release版本都在github: https://github.com/nicai0609/JAVA-CTPAPI/可下。


1.准备工作

完全参考文章CTP JAVA API(JCTP)编译(利用Swig封装C++动态库)windows版中的准备工作就可以了,注意jdk和libiconv都要是64位的。github上有编译好的libconv的静态库,不放心也可以到qq群里文件共享区下载vs2013的源码自己编译。
本文一开始采用的是第三方库libiconv转换,下面也以libiconv为例继续。C++11库中已有字节编码转换方式,采用这种方式可以不用libiconv库,下面和libiconv相关的都可以略去,见《Swig转换C++接口中文乱码解决方案》
另外,我们在下载好的20180109_tradeapi64_windows文件夹中预先建一些文件夹,结构图如下:

20180109_tradeapi64_windows

│─── ctp ─── thostapi

│─── demo

│─── src

│─── wrap

│ ThostFtdcMdApi.h
│ ThostFtdcTraderApi.h
│ ThostFtdcUserApiDataType.h
│ …

2.通过Swig得到jar包

在刚刚下载得到的API文件夹20180109_tradeapi64_windows内,新建文件thostap.i,内容如下

%module(directors="1") thosttraderapi 
%include "various.i"
%apply char **STRING_ARRAY { char *ppInstrumentID[] }
%{ 
#include "ThostFtdcMdApi.h"
#include "ThostFtdcTraderApi.h"
#include "iconv.h"
%}

%typemap(out) char[ANY], char[] {
    if ($1) {
        iconv_t cd = iconv_open("utf-8", "gb2312");
        if (cd != reinterpret_cast<iconv_t>(-1)) {
            char buf[4096] = {};
            char **in = &$1;
            char *out = buf;
            size_t inlen = strlen($1), outlen = 4096;

            if (iconv(cd, in, &inlen, &out, &outlen) != static_cast<size_t>(-1))
                $result = JCALL1(NewStringUTF, jenv, (const char *)buf);
            iconv_close(cd);
        }
    }
}

%feature("director") CThostFtdcMdSpi;
%ignore THOST_FTDC_VTC_BankBankToFuture;
%ignore THOST_FTDC_VTC_BankFutureToBank;
%ignore THOST_FTDC_VTC_FutureBankToFuture;
%ignore THOST_FTDC_VTC_FutureFutureToBank;
%ignore THOST_FTDC_FTC_BankLaunchBankToBroker;
%ignore THOST_FTDC_FTC_BrokerLaunchBankToBroker;
%ignore THOST_FTDC_FTC_BankLaunchBrokerToBank;
%ignore THOST_FTDC_FTC_BrokerLaunchBrokerToBank;
%include "ThostFtdcUserApiDataType.h"
%include "ThostFtdcUserApiStruct.h" 
%include "ThostFtdcMdApi.h"
%feature("director") CThostFtdcTraderSpi;
%include "ThostFtdcTraderApi.h"

various.i文件是swig自带的,将swig/Lib/java/various.i拷贝过来即可。然后再当前目录cmd下运行命令:

swig.exe -c++ -java -package ctp.thostapi -outdir src -o thosttraderapi_wrap.cpp thostapi.i

等到运行完成后,可以看到当前目录下生成了

thosttraderapi_wrap.h
thosttraderapi_wrap.cpp

这两个文件是用于包装原来C++接口的文件,下面要用。打开src文件夹,可以看到这时在里面生成了一系列方法的java文件,如下:

CThostFtdcAccountregisterField.java
CThostFtdcAuthenticationInfoField.java
… … …
thosttradeapiJNI.java

cmdcdsrc文件夹底下,运行命令

javac *.java

运行结束之后可以看到生成了等量的class文件,将所有的class文件拷贝到\ctp\thostapi\文件夹中,cmdcd20180109_tradeapi64_windows目录下,运行命令

jar cf thostapi.jar ctp

这样我们就在当前文件夹下得到了jar包thostapi.jar

3.通过C++得到java可调用的dll动态库

这一步也完全参考文章CTP JAVA API(JCTP)编译(利用Swig封装C++动态库)windows版,只不过工程名我这里改成了thostapi_wrap。编译完成之后就能在x64文件夹底下得到动态库thostapi_wrap.dll
windows下是建vs工程编译生成dll,linux下可以参考github上的makefile编译生成thostapi_wrap.so。除了这一步,以上在windows上和linux上32位,64位都是通用的,不需要重复做。

4.Demo

这里给出一个订阅全市场行情的demo,可以到githuab上直接导入该工程,将账号密码交易及行情前置地址改成自己的就可以运行。

import ctp.thostapi.*;
import java.util.Vector;
import java.util.Iterator;

class TraderSpiImpl extends CThostFtdcTraderSpi{	
	final static String m_BrokerId = "9999";
	final static String m_UserId = "070624";
	final static String m_InvestorId = "070624";
	final static String m_PassWord = "passwd"; 
	final static String m_TradingDay = "20181122";
	final static String m_AccountId = "070624";
	final static String m_CurrencyId = "CNY";
	TraderSpiImpl(CThostFtdcTraderApi traderapi,Vector<String> instrs)
	{
		m_traderapi =  traderapi;
		m_instr_vec = instrs;
	}
	
	@Override
	public void OnFrontConnected(){
		System.out.println("On Front Connected");
		CThostFtdcReqUserLoginField field = new CThostFtdcReqUserLoginField();
		field.setBrokerID(m_BrokerId);
		field.setUserID(m_UserId);
		field.setPassword(m_PassWord);
		field.setUserProductInfo("JAVA_API");
		m_traderapi.ReqUserLogin(field,0);
		System.out.println("Send login ok");
	}
	
	@Override
	public void OnRspUserLogin(CThostFtdcRspUserLoginField pRspUserLogin, CThostFtdcRspInfoField pRspInfo, int nRequestID, boolean bIsLast)
	{
		if (pRspInfo != null && pRspInfo.getErrorID() != 0)
		{
			System.out.printf("Login ErrorID[%d] ErrMsg[%s]\n", pRspInfo.getErrorID(), pRspInfo.getErrorMsg());

			return;
		}
		System.out.println("Login success!!!");
		CThostFtdcQryTradingAccountField qryTradingAccount = new CThostFtdcQryTradingAccountField();
		qryTradingAccount.setBrokerID(m_BrokerId);
		qryTradingAccount.setCurrencyID(m_CurrencyId);;
		qryTradingAccount.setInvestorID(m_InvestorId);
		//m_traderapi.ReqQryTradingAccount(qryTradingAccount, 1);
		
		CThostFtdcQrySettlementInfoField qrysettlement = new CThostFtdcQrySettlementInfoField();
		qrysettlement.setBrokerID(m_BrokerId);
		qrysettlement.setInvestorID(m_InvestorId);
		qrysettlement.setTradingDay(m_TradingDay);
		qrysettlement.setAccountID(m_AccountId);
		qrysettlement.setCurrencyID(m_CurrencyId);
		//m_traderapi.ReqQrySettlementInfo(qrysettlement, 2);
		
		CThostFtdcQryInstrumentField qryInstr = new CThostFtdcQryInstrumentField();
		m_traderapi.ReqQryInstrument(qryInstr, 3);
		System.out.println("Query success!!!");
	}
	
	@Override
	public void OnRspQryTradingAccount(CThostFtdcTradingAccountField pTradingAccount, CThostFtdcRspInfoField pRspInfo, int nRequestID, boolean bIsLast) 
	{
		if (pRspInfo != null && pRspInfo.getErrorID() != 0)
		{
			System.out.printf("OnRspQryTradingAccount ErrorID[%d] ErrMsg[%s]\n", pRspInfo.getErrorID(), pRspInfo.getErrorMsg());

			return;
		}
		
		if (pTradingAccount != null)
		{
			System.out.printf("Balance[%f]Available[%f]WithdrawQuota[%f]Credit[%f]\n",
				pTradingAccount.getBalance(), pTradingAccount.getAvailable(), pTradingAccount.getWithdrawQuota(),
				pTradingAccount.getCredit());
		}
		else
		{
			System.out.printf("NULL obj\n");
		}
	}
	
	public void  OnRspQrySettlementInfo(CThostFtdcSettlementInfoField pSettlementInfo, CThostFtdcRspInfoField pRspInfo, int nRequestID, boolean bIsLast)
	{
		if (pRspInfo != null && pRspInfo.getErrorID() != 0)
		{
			System.out.printf("OnRspQrySettlementInfo ErrorID[%d] ErrMsg[%s]\n", pRspInfo.getErrorID(), pRspInfo.getErrorMsg());

			return;
		}
		
		if (pSettlementInfo != null)
		{
			System.out.printf("%s",pSettlementInfo.getContent());
		}
		else
		{
			System.out.printf("NULL obj\n");
		}
	}
	
	public void OnRspQryInstrument(CThostFtdcInstrumentField pInstrument, CThostFtdcRspInfoField pRspInfo, int nRequestID, boolean bIsLast)
	{
		if (pRspInfo != null && pRspInfo.getErrorID() != 0)
		{
			System.out.printf("OnRspQryInstrument ErrorID[%d] ErrMsg[%s]\n", pRspInfo.getErrorID(), pRspInfo.getErrorMsg());
			return;
		}
		if (pInstrument != null)
		{
			//System.out.printf("%s\n",pInstrument.getInstrumentID());
			m_instr_vec.add(pInstrument.getInstrumentID());
		}
		else
		{
			System.out.printf("NULL obj\n");
		}
	}
	
	private CThostFtdcTraderApi m_traderapi;
	private Vector<String> m_instr_vec;
}

class mdspiImpl extends CThostFtdcMdSpi{
	final static String m_BrokerId = "9999";
	final static String m_UserId = "070624";
	final static String m_InvestorId = "070624";
	final static String m_PassWord = "passwd"; 
	final static String m_TradingDay = "20181122";
	final static String m_AccountId = "070624";
	final static String m_CurrencyId = "CNY";
	mdspiImpl(CThostFtdcMdApi mdapi,Vector<String> instrs)
	{
		m_mdapi =  mdapi;
		m_instr_vec = instrs;
	}
	
	public void OnFrontConnected(){
		System.out.println("On Front Connected");
		CThostFtdcReqUserLoginField field = new CThostFtdcReqUserLoginField();
		field.setBrokerID(m_BrokerId);
		field.setUserID(m_UserId);
		field.setPassword(m_PassWord);
		m_mdapi.ReqUserLogin(field, 0);
		
	}
	
	public void OnRspUserLogin(CThostFtdcRspUserLoginField pRspUserLogin, CThostFtdcRspInfoField pRspInfo, int nRequestID, boolean bIsLast) {
		if (pRspUserLogin != null) {
			System.out.printf("Brokerid[%s]\n",pRspUserLogin.getBrokerID());			
		}
		String[] instruementid = new String[1];
		Iterator iterator = m_instr_vec.iterator();
        while (iterator.hasNext()) {
        	instruementid[0]=iterator.next().toString();
        	m_mdapi.SubscribeMarketData(instruementid,1);
            System.out.println(instruementid[0]);
        }
	}
	
	public void OnRtnDepthMarketData(CThostFtdcDepthMarketDataField pDepthMarketData) {
		if (pDepthMarketData != null)
		{
			System.out.printf("InstrumentID[%s]AskPrice1[%f]BidPrice1[%f]\n",
					pDepthMarketData.getInstrumentID(),pDepthMarketData.getAskPrice1(),pDepthMarketData.getBidPrice1());
		}
		else
		{
			System.out.printf("NULL obj\n");
		}
	}	
	private CThostFtdcMdApi m_mdapi;
	private Vector<String> m_instr_vec;
}


public class demo {

	static{
		System.loadLibrary("thosttraderapi");
		System.loadLibrary("thostmduserapi");
		System.loadLibrary("thostapi_wrap");
	}
	final static String ctp1_TradeAddress = "tcp://180.168.146.187:10000";
	final static String ctp1_MdAddress = "tcp://180.168.146.187:10010";
	static Vector<String> instr_vec = new Vector<String>();
	public static void main(String[] args) {
		//System.out.println(System.getProperty("java.library.path"));
		CThostFtdcTraderApi traderApi = CThostFtdcTraderApi.CreateFtdcTraderApi("trade");
		TraderSpiImpl pTraderSpi = new TraderSpiImpl(traderApi,instr_vec);
		traderApi.RegisterSpi(pTraderSpi);
		traderApi.RegisterFront(ctp1_TradeAddress);
		traderApi.SubscribePublicTopic(THOST_TE_RESUME_TYPE.THOST_TERT_QUICK);
		traderApi.SubscribePrivateTopic(THOST_TE_RESUME_TYPE.THOST_TERT_QUICK);
		traderApi.Init();
		//这里sleep是为了保证traderapi的登录查询成功
		try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace(); 
        }
		CThostFtdcMdApi mdApi = CThostFtdcMdApi.CreateFtdcMdApi("md");
		mdspiImpl pMdspiImpl = new mdspiImpl(mdApi,instr_vec);
		mdApi.RegisterSpi(pMdspiImpl);
		mdApi.RegisterFront(ctp1_MdAddress);
		mdApi.Init();
		
		traderApi.Join();
		mdApi.Join();
		return;
	}
}
  • 8
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
JCTP 0.3.2 2013-2-27 增加:JCTPStructUtil工具类 修正:交易API部分函数出现空指针异常的问题 修正:行情API部分函数出现空指针异常的问题 变更:发布包中增加JCTP.jar *********************************************** JCTP 0.3.1 2013-2-26 修正:交易API部分函数出现空指针异常的问题 *********************************************** JCTP 0.3 2013-2-26 增加:完成对交易API的封装 增加:格式化结构体方法注释为javadoc格式(暂未转成中文) 增加:优化结构体属性的调用方式,增加getter/setter方法,隐藏bridj框架代码 修正:解决Bridj框架中一处与CTP接口的兼容问题 修正:解决回调方法中结构体的属性值为中文时出现乱码的问题 变更:移动util包到jctp路径下 变更:发布版本号格式更改,缩进1位 *********************************************** JCTP 0.0.2 2013-1-31 增加:JCTPLibraryUtil类,用于初始化CTP环境或卸载CTP环境 增加:JCTPMdApi类,将Bridj调用CTP的代码隐藏 增加:JCTPMdSpi类,将Bridj调用CTP的代码隐藏 增加:JCTPTraderApi类,将Bridj调用CTP的代码隐藏 增加:JCTPTraderSpi类,将Bridj调用CTP的代码隐藏 修正:Spi回调时报空指针,无法进入回调方法的问题 修正:无法调用带参数的CreateFtdc.....Api函数的问题 修正:只能在调试模式下进行回调的问题 变更:CTP动态链接库置入jar包 变更:将JCTP相关类独立出CTP调用包

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值