from jqlib.technical_analysis import *
import pandas as pd
import numpy as np
import math
from sklearn.svm import SVR
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import learning_curve
from sklearn.linear_model import LinearRegression
from sklearn.ensemble import RandomForestRegressor
import jqdata
from sklearn.ensemble import RandomForestClassifier
import datetime
from sklearn.tree import DecisionTreeRegressor
from sklearn.tree import DecisionTreeClassifier
def initialize(context):
set_params()# #设置策略参数
set_backtest()#设置回测条件
set_variables()
# run_daily(trade, 'every_bar')# 开盘时运行
def set_params():
# g.refresh_rate = 10
g.tc=1 # 调仓频率,这里为10天一次
g.stocknum = 6#持仓数目,这里为10个股票
g.ret=-0.05
def set_backtest():
set_benchmark('000300.XSHG')#设置对比基本,这里为沪深300
set_option('use_real_price', True)#使用真实价格成交
log.set_level('order', 'error')
def set_variables():
g.days = 0# # 记录回测运行的天数
g.if_trade = False
# 开盘之前需要做的事:
def before_trading_start(context):
if g.days%g.tc==0:
g.if_trade=True # 每g.tc天,调仓一次
set_slip_fee(context) # 设置手续费与手续费
g.stocks=get_index_stocks('000300.XSHG') # 设置沪深300为初始股票池
# 设置可行股票池
g.feasible_stocks = set_feasible_stocks(g.stocks,context)
g.days+=1
#4
# 设置可行股票池:过滤掉当日停牌的股票
# 输入:initial_stocks为list类型,表示初始股票池; context(见API)
# 输出:unsuspened_stocks为list类型,表示当日未停牌的股票池,即:可行股票池
def set_feasible_stocks(initial_stocks,context):
# 判断初始股票池的股票是否停牌,返回list
paused_info = []
current_data = get_current_data()
for i in initial_stocks:
paused_info.append(current_data[i].paused)
df_paused_info = pd.DataFrame({'paused_info':paused_info},index = initial_stocks)
stock_list =list(df_paused_info.index[df_paused_info.paused_info == False])
return stock_list
# 根据不同的时间段设置滑点与手续费
# 输入:context(见API)
# 输出:none
def set_slip_fee(context):
# 将滑点设置为0
set_slippage(FixedSlippage(0.02))
# 根据不同的时间段设置手续费
dt=context.current_dt
if dt>datetime.datetime(2013,1, 1):
set_commission(PerTrade(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))
elif dt>datetime.datetime(2011,1, 1):
set_commission(PerTrade(buy_cost=0.001, sell_cost=0.002, min_cost=5))
elif dt>datetime.datetime(2009,1, 1):
set_commission(PerTrade(buy_cost=0.002, sell_cost=0.003, min_cost=5))
else:
set_commission(PerTrade(buy_cost=0.003, sell_cost=0.004, min_cost=5))
# 每天回测时做的事情
def handle_data(context,data):
if g.if_trade == True:
# 待买入的g.num_stocks支股票,list类型
list_to_buy = stocks_to_buy(context)
# 待卖出的股票,list类型
list_to_sell = stocks_to_sell(context, list_to_buy)
# 卖出操作
sell_operation(list_to_sell)
# 买入操作
buy_operation(context, list_to_buy)
g.if_trade = False
def get_rff(context,stock_list):
q = query(valuation.code, valuation.market_cap,balance.total_current_assets- balance.total_current_liability,
balance.total_liability- balance.total_assets,balance.total_liability/balance.equities_parent_company_owners,
(balance.total_assets-balance.total_current_assets)/balance.total_assets,
balance.equities_parent_company_owners/balance.total_assets,
indicator.inc_total_revenue_year_on_year,valuation.turnover_ratio,
valuation.pe_ratio,valuation.pb_ratio,valuation.ps_ratio,indicator.roa).filter(valuation.code.in_(stock_list))
df = get_fundamentals(q, date = None)
df.columns = ['code', '市值', '净营运资本', '净债务', '产权比率','非流动资产比率','股东权益比率', '营收增长率'
,'换手率','PE','PB','PS','总资产收益率']
df.index = df.code.values
del df['code']
start= datetime.datetime.now()
delta50= datetime.timedelta(days=50)
delta1= datetime.timedelta(days=1)
today=start-delta1
preday=start-delta50
df['动量线']=list(MTM(df.index, today, timeperiod=10, unit = '1d', include_now = True, fq_ref_date = None).values())
# print(df['动量线'])
df['成交量']=list(VOL(df.index, today, M1=10 ,unit = '1d', include_now = True, fq_ref_date = None)[0].values())
df['累计能量线']=list(OBV(df.index,check_date=today, timeperiod=10).values())
df['资金流量指标']=list(MFI(df.index, today, timeperiod=10, unit = '1d', include_now = True, fq_ref_date = None).values())
df['平均差']=list(DMA(df.index, today, N1 = 10, unit = '1d', include_now = True, fq_ref_date = None)[0].values())
df['指数移动平均']=list(EMA(df.index, today, timeperiod=10, unit = '1d', include_now = True, fq_ref_date = None).values())
df['移动平均']=list(MA(df.index, today, timeperiod=10, unit = '1d', include_now = True, fq_ref_date = None).values())
df['乖离率']=list(BIAS(df.index,today, N1=10, unit = '1d', include_now = True, fq_ref_date = None)[0].values())
df.fillna(0,inplace=True)
df=df.apply(lambda x : (x-np.min(x))/(np.max(x)-np.min(x)))
df['close1']=get_price(stock_list, start_date=today, end_date=today, fq='pre',panel=False)['close'].T
df['close2']=get_price(stock_list, start_date=preday, end_date=preday, fq='pre',panel=False)['close'].T
df['return']=df['close1']/df['close2']-1
df['signal']=np.where(df['return']<df['return'].mean(),0,1)
x=df[['市值', '净营运资本', '净债务', '产权比率','非流动资产比率','股东权益比率', '营收增长率'
,'换手率','PE','PB','PS','总资产收益率','成交量',
'累计能量线','资金流量指标','平均差','指数移动平均','移动平均','乖离率']]
y=df[['signal']]
x=x.fillna(0)
y=y.fillna(0)
tree=DecisionTreeClassifier()
tree.fit(x,y)
model_cs=pd.DataFrame({'feature':list(x.columns),'importance':tree.feature_importances_}).sort_values('importance',ascending=False)
rff=RandomForestClassifier(n_estimators=1000, criterion='gini',
max_depth=None, min_samples_split=2,
min_samples_leaf=1, max_features='auto',
bootstrap=True, oob_score=False, n_jobs=1,
random_state=None, verbose=0)
rff.fit(x,y)
model_cs=pd.DataFrame({'feature':list(x.columns),'importance':rff.feature_importances_}).sort_values('importance',ascending=False)
xq=model_cs['feature'][:10]
dff=df[xq]
dff['市值']=df['市值']
X=df[xq]
Y=df['市值']
X=X.fillna(0)
Y=Y.fillna(0)
rf = RandomForestRegressor()
model = rf.fit(X, Y)
factor = Y - pd.DataFrame(rf.predict(X), index = Y.index, columns = ['市值'])
factor = factor.sort_index(by = '市值')
return factor
# 买入信号:
def stocks_to_buy(context):
list_to_buy=[]
day1=context.current_dt
day2= day1-datetime.timedelta(days=5)
hs300_clos=get_price('000300.XSHG',day2,day1 , fq='pre')['close']
hs300_ret=hs300_clos[-1]/hs300_clos[0]-1
print('今天是:%s'%day1)
print('hs300_ret:%s'%hs300_ret)
if hs300_ret>g.ret:
factor = get_rff(context, g.feasible_stocks)
list_to_buy = list(factor.index[:g.stocknum])
print('买入股票:%s' %list_to_buy)
else:
pass
return list_to_buy
# 获得卖出信号
# 输入:context(见API文档), list_to_buy为list类型,代表待买入的股票
# 输出:list_to_sell为list类型,表示待卖出的股票
def stocks_to_sell(context, list_to_buy):
# 对于不需要持仓的股票,全仓卖出
list_to_sel
评论3