之前公司业务部门提出需要做wind 新债数据对比,原本做的方案是 直接 从数据中心wind库中获取,但是数据中心wind库,并非实时数据而是 每半个小时由wind 主动推送的数据,业务觉得不满足要求,需要wind 最新实时数据;
根据业务要求,查找到 wind 资讯端 提供的 接口,有C、C#、python 等其他接口,本人看一下,选择使用python 来实现;大概逻辑:业务在web端 业务系统 填写需要获取的新债信息(wind代码 和 市场),然后由java 程序处理相关逻辑后,调用python提供的http协议get接口, 最后通过python 程序调用 wind接口获取到数据,返回字符串给java 程序,java 程序解析后 在系统上展示 新债信息;
一、搭建python 环境(建议采用3.0及其以上,3.0以下好像不维护了),本人使用的3.5版本,环境搭建有很多,可以自行百度,也可参考本人另一篇文章;
二、python 端 代码(本人python零基础,代码规范 语法啥的 不是很会,这是一位同事提供的相关代码)
注意这里需要 安装相关包:flask、flask_restful;其他如果 运行报错,报什么不存在,可能是包没有安装,可以尝试安装后在运行。
注意:“WindPy ”这个是 wind 的包,需要在 python 环境中 安装wind 资讯端,安装完成后,在wind终端里面 找到菜单【量化】->【修复插件】-【python】;注意第一次需要 配置python接口信息路径,我的路径是(这里我3.5 和 3.7都安装了,只要一个就可以了):
配置好后修复一下。
python代码:新建python文件 XX.py;
# -*- coding: utf-8 -*-
"""
Spyder Editor
This is a temporary script file.
"""
from flask import Flask, request
from flask_restful import Resource, Api
from json import dumps
from flask import jsonify
from WindPy import w #wind 包
import logging
import datetime
import logging
app = Flask(__name__)
api = Api(app)
class CJHX_Data_Service(Resource):
def get(self, windcode):
try:
logging.info('-------call_wind_openapi()--------')
#调用wind接口,这里先判断是否已经启动了
if not w.isconnected():
w.start()
now = datetime.datetime.now()
nowday = now.strftime("%Y-%m-%d")
wed = w.wsd(windcode,"issue_issueprice,agency_trustee,dirtyprice,cleanprice,windl2type,sec_name,trade_code,carrydate,maturitydate,embeddedopt,latestpar,paymenttype,interestfrequency,repaymentmethod,couponrate,taxfree,windcode,redemptiondate,repurchasedate,subordinateornot,taxrate,coupon,interesttype",nowday,nowday,"")
result = str(wed.Data)
#w.stop() 这里取消关闭,wind接口每隔120秒会自动关闭,无需手工关闭,避免接口并发时导致程序异常掉
return result
except Exception as e:
logging.error('call_wind_openapi raise an error ', e)
api.add_resource(CJHX_Data_Service, '/api/<windcode>') # Route_3
if __name__ == '__main__':
app.run(port=7788,debug=True,host="0.0.0.0")
#curl http://127.0.0.1:7789/api/8
代码说明:
w.wsd() 是wind接口,接口使用 请参考wind接口说明,里面有详细讲解;大概就是 wind代码、需要的wind字段(需要通过wind端获取)、查询开始时间、查询结束时间;
wind 字段选择:量化-api接口-代码生成器 ;语言选择python,我这里选择第一个日期序列;点击后任意选择一个债券;然后下一个,就可以找中文字段对应的 wind 字段了;
7788 是端口,这里有你可以任意写,0.0.0.0 代表可以通过ip访问。
完成后在浏览器输入 http://127.0.01:7788/api/114411.SZ (114411.SZ 代表wind 代码 + 市场);
三、java 端代码【没有什么好说,直接看代码吧】
jar 引用
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.lang.Integer;
import java.net.URL;
import java.net.URLConnection;
调用的方法
public static String windApi(String code,String jysc){
String windcode="";
String temp="";
if("上海".equals(jysc)){
windcode = code+".SH";
}else if("深圳".equals(jysc)){
windcode = code+".SZ";
}else if("银行间".equals(jysc)){
windcode = code+".IB";
}else{
return null;
}
try {
String endpoint = "http://10.201.9.95:7788/api/"+windcode;
//String endpoint = "http://10.201.224.125:7788/api/"+windcode;
String result = (String) sendGet(endpoint);
result=result.replace("\"","");
// 给方法传递参数,并且调用方法
System.out.println("result is " + result);
/***
* 解析接口返回值字符串 这里 我直接返回字符串,做了字符串解析,和中文处理;
*/
String str = result.replace("[","");
str = str.replace("]]","");
String[] strs = str.split("],");
for(int i=0;i<strs.length;i++){
String t = strs[i].replace("u'","");
t=t.replace("'","");
t=t.replace(" ","");
if(t.split("datetime").length>2){
t= getUnTime(t);
}
if(i==0){
temp=unicodeToCn(t);
}else{
temp=temp+","+unicodeToCn(t);
}
}
System.out.println(temp);
} catch (Exception e) {
System.err.println(e.toString());
}
return temp;
}
其他辅助方法:
/**
* 解析wind 时间返回值
* @param t
* @return 数字类型时间
*/
public static String getUnTime(String t){
String a = t.replace("datetime","");
String[] f = a.split(",");
String year = f[0].replace("(","").replace(".","");
String mm = f[1].length()<2?"0"+f[1]:f[1];
String dd = f[2].length()<2?"0"+f[2]:f[2];
t=year+""+mm+""+dd;
return t;
}
public static String getNumTime(String t){
String[] f = t.split("-");
String year = f[0];
String mm = f[1].length()<2?"0"+f[1]:f[1];
String dd = f[2].length()<2?"0"+f[2]:f[2];
t=year+""+mm+""+dd;
return t;
}
/**
* 解析uncode编码 中文 u'18\u9633\u716404'
* @param unicode
* @return
*/
private static String unicodeToCn(String unicode) {
/** 以 \ u 分割,因为java注释也能识别unicode,因此中间加了一个空格*/
String[] strs = unicode.split("\\\\u");
String returnStr = "";
//必须包含\\u 否则原样输出
if(strs.length<2){
return unicode;
}
for (int i = 0; i < strs.length; i++) {
String t = strs[i];
//非中文则没有被编码,例如数字在前,目前不考虑大于四位的情况
if(t.length()<4){
returnStr +=t;
continue;
}
String s = "";
//非中文则没有被编码,例如数字在后
if(t.length()>4){
s =t.substring(4, t.length());
t =t.substring(0, 4);
}
returnStr += (char) Integer.valueOf(t, 16).intValue() +s;
}
return returnStr;
}
public static String getNumber(String s){
String a = s.split("\\.")[0];
if(Double.parseDouble(s) == Double.parseDouble(a)){
return a;
}else{
return s;
}
}
//发送GET请求
public static String sendGet(String url) {
String result = "";
BufferedReader in = null;
try {
String urlName = url;
URL realUrl = new URL(urlName);
URLConnection conn = realUrl.openConnection();// 打开和URL之间的连接
conn.setRequestProperty("accept", "*/*");// 设置通用的请求属性
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
conn.setConnectTimeout(4000);
conn.connect();// 建立实际的连接
in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));// 定义BufferedReader输入流来读取URL的响应
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送GET请求出现异常!" + e);
} finally {// 使用finally块来关闭输入流
try {
if (in != null) {
in.close();
}
} catch (Exception ex) {
System.out.println("关闭流异常");
}
}
return result;
}
四、写一个main方法执行调用就行了,注意要先运行python程序;
如果报错 请跟进报错解决吧,我貌似没有遇到什么问题;
在ip访问遇到了一个问题,启动了多个python ,导致ip访问不生效,把其他的相同端口python杀死就行了,
public static void main(String[] args) {
windApi("114411","深圳");
}