用python的flask框架将我已经写好的函数封装成API供我的JavaWeb项目调用
# -*- coding: utf-8 -*-
"""
Created on Sun Aug 4 09:15:26 2019
@author: Mr. Wang
"""
import tushare as ts
import matplotlib as mpl
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from flask import Flask,jsonify,request
import json
app = Flask(__name__)#创建一个服务,赋值给APP
data = ts.get_stock_basics()
@app.route('/stock3',methods=['get'])
def test():
s1 = request.args.get('s1')
s2 = request.args.get('s2')
s3 = request.args.get('s3')
callback = request.args.get('callback')
codes_in=[
'000977','300383','600410'
]
codes_in[0] = s1
codes_in[1] = s2
codes_in[2] = s3
for c in codes_in:
df=ts.get_hist_data(c,start='2019-09-01',end='2020-04-30')
df.to_csv('assets'+c+'.csv')
codes={} #创建字典
for s in codes_in:
codes[s]=data.loc[s, 'name']
symbols=codes.keys() #所有股票名称作为key值
def col_converter(x): #定义函数
try:
return float(x)
except:
return None
prices=None
for i,s in enumerate(symbols): #穷举
p=pd.read_csv('assets'+s.upper()+'.csv',
usecols=['close','date'],index_col='date',
converters={'close':col_converter}, engine='python')#engine = 'python' 不然打不开文件
if i==0:
prices=pd.DataFrame(index=p.index)#创建dataframe
prices[s]=p['close'] #初始化每一列
prices.sort_index(ascending=True,inplace=True) #升序排列
prices.dropna(inplace=True) #去掉空值
co=prices.pct_change().corr()#相关系数dataframe
for symbol in symbols:
v=co[symbol].sort_values() #按相关系数升序
print (symbol,u' | 正相关度最高: ',v.index[-2],u' 相关系数=',v[-2],u' | 负相关度最高: ',v.index[0],u' 相关系数=',v[0])
print ('')
#将股票分为
from sklearn.cluster import affinity_propagation
_,labels=affinity_propagation(co)
symbolx = list(symbols)#须转换为list
df_c=pd.DataFrame({'label':labels,'name':symbolx})
g=df_c.groupby('label')
for item in g:
x = item[1]['name'].values
print (item[0],','.join(x))
print ('=============')
# prices.pct_change().hist(column=[u'浪潮信息',u'光环新网',u'华胜天成',u'中兴通讯' , u'东方通', u'浪潮软件', u'中科曙光'],
# sharex=True,sharey=True,bins=30)
#
weights = np.random.random(3)
weights /= np.sum(weights)
weights
log_returns = np.log(prices.pct_change()+1)
log_returns = log_returns.dropna()
#投资组合的风险(9个交易日,标准差)
np.sqrt(np.dot(weights, np.dot(log_returns.cov()*160, weights)))#九个交易日
#随机生成1000种随机的投资组合,即权重weight的尺寸为1000*9
port_returns = []
port_variance = []
for p in range(1000):
weights = np.random.random(3)
weights /=np.sum(weights)
port_returns.append(np.sum(log_returns.mean()*160*weights))
port_variance.append(np.sqrt(np.dot(weights.T, np.dot(log_returns.cov()*160, weights))))
port_returns = np.array(port_returns)
port_variance = np.array(port_variance)
#无风险利率设定为3
risk_free = 0.03
#优化,夏普率最大
import scipy.optimize as sco
def stats(weights):
weights = np.array(weights)
port_returns = np.sum(log_returns.mean()*weights)*160
port_variance = np.sqrt(np.dot(weights.T,np.dot(log_returns.cov()*160,weights)))
return np.array([port_returns,port_variance,port_returns/port_variance])
def min_sharpe(weights):
return-stats(weights)[2]
#给定初始权重
#权重(某股票持仓比例)限制在0和1之间。
x0 =3*[1./3]
bnds = tuple((0,1) for x in range(3))
#权重(股票持仓比例)的总和为1。
cons = ({'type':'eq','fun':lambda x: np.sum(x)-1})
#优化函数调用中忽略的唯一输入是起始参数列表(对权重的初始猜测)。我们简单的使用平均分布。
opts = sco.minimize(min_sharpe,x0,method ='SLSQP',bounds = bnds,constraints = cons)
opts
output = opts['x'].round(3)
#sharpe最大的组合3个统计数据分别为:
stats(opts['x']).round(3)
def min_variance(weights):
return stats(weights)[1]
optv = sco.minimize(min_variance,
x0,
method ='SLSQP',
bounds = bnds,
constraints = cons)
optv
optv['x'].round(3)
#得到的投资组合预期收益率、波动率和夏普指数
stats(optv['x']).round(3)
#定义一个函数对方差进行最小化
def min_variance(weights):
return stats(weights)[1]
return "raybu("+json.dumps(output.tolist()) +");"
app.run(host='0.0.0.0',port=8806,debug=True)
主要就是函数前后的两条语句,前面的那条语句设置了映射,也就是访问路径;后面的那条语句设置了端口号。
函数夹在两条语句中间就可以。
访问http://192.168.3.13:8806/stock3?s1=000977&s2=600519&s3=000708,会得到raybu([0.xx,0.xx,0.xx])。
这是推荐的各个股票配置权重,具体的分析步骤这里就不说了。
为什么要加一个raybu()把这个数组包起来呢?
因为我调试的时候要跨域调用API!
对于我的情况,简单来说就是我在本机开了tomcat运行web项目,在这个web项目中又调用了在本机运行的API,根据同源策略,这是不允许的!
所以就需要用一个回调函数把要传的数据包起来,用jsonp的方式传递,在我的api中就是raybu(),并且在客户端的JQuery语句的url中也要加入callback=?,并定义回调函数名为raybu,如下:
var getAdvise = function ()
{
var formObj=document.form1;
var code1 = formObj.s1.value;
var code2 = formObj.s2.value;
var code3 = formObj.s3.value;
//var str = {
//s1: code1,
// }传递参数为json时使用
alert(code1+code2+code3+durl)
//方式一:通过ajax的方式获取数据
$.ajax({
url:"http://192.168.3.13:8806/stock3?s1="+code1+"&s2=" + code2 + "&s3="+code3+"&callback=?",
type: 'get',
timeout: 100000,
dataType: 'jsonp',
processData: false,
jsonpCallback:"raybu",
success: function(data){
alert("success!");
$("#output")[0].innerText=data ;
console.log("fafafaf");
},
error:function(XMLHttpRequest, textStatus, errorThrown) {
alert(XMLHttpRequest.status);
alert(XMLHttpRequest.readyState);
alert(textStatus);
}
});
return false;
}
关于JS跨域请求的各种详细解释,我找到了下面几篇文章:
看完后应该就能解决关于JS跨域请求的各种问题了
flask实现pythonAPI注意事项
注意文件路径映射语句和接口开放语句的位置
注意端口是否被占用
注意映射的文件路径是否访问正确
注意return的格式
最重要的一点,如果客户端调用报错,检查是否跨域!