[QUANTAXIS量化分析]三因素模型
基本原理
- 三因素模型表达式:
E(Rit) − Rft = βi[E(Rmt − Rft] + siE(SMBt) + hiE(HMIt)
- 根据一篇文章,选择三个因子作测试:
- 财务因子:EPS
- 成交量因子:log(30日日均交易量/昨日交易量)
- 反转因子:(ma10-ma5)/ma5
- 综合选取这三个因子,0.3,0.4,0.3的权值加和,选取较高的股票并持仓。综合选取这三个因子,0.3,0.4,0.3的权值加和,选取较高的股票并持仓。
策略实现
- 初始资金100万,20万无明显效果差异,时间段为2017-01-01~2018-01-01.
- 选取市盈率0~20之间的股票,每日对三因子加和进行排序
- 每天进行判断,选取三因子加和排名前n的股票,若已持股,继续买入,未持股则买入,已持股中有不在排名前n中的,卖出。
- (每日操作10只股票)运行截图(忽略曲线名):
- (每日操作20只股票)运行截图(忽略曲线名):
遇到的问题及改进:
- 采用的三个因子或许还能有其他财务因子进行代表
- 本次代码中取得EPS的时间有些过长,有点想法,等我后面改进(已改进,不必每只股票每天的eps都获取一次)
代码如下:
# coding: utf-8
# @author: lin
# @date: 2018/11/20import QUANTAXIS as QA
import datetime
import pandas as pd
import time
import math
import matplotlib.pyplot as plt
import numpy as nppd.set_option('max_colwidth', 5000)
pd.set_option('display.max_columns', 5000)
pd.set_option('display.max_rows', 5000)class ThreePara:def __init__(self, start_time, stop_time, n_stock=10, stock_init_cash=1000000, n_days_before=1):self.Account = QA.QA_Account() # 初始化账户self.Account.reset_assets(stock_init_cash) # 初始化账户self.Account.account_cookie = 'three_para'self.Broker = QA.QA_BacktestBroker()self.time_quantum_list = ['-12-31', '-09-30', '-06-30', '-03-31']self.start_time = start_timeself.stop_time = stop_timeself.n_days_before = n_days_beforeself.stock_pool = []self.data = Noneself.ind = Noneself.n_stock = n_stockself.get_stock_pool()def get_financial_time(self):"""得到此日期前一个财务数据的日期:return:"""year = self.start_time[0:4]while (True):for day in self.time_quantum_list:the_financial_time = year + dayif the_financial_time <= self.start_time:return the_financial_timeyear = str(int(year) - 1)def get_assets_eps(self, stock_code, the_financial_time):"""得到高级财务数据:param stock_code::param the_financial_time: 离开始时间最近的财务数据的时间:return:"""financial_report = QA.QA_fetch_financial_report(stock_code, the_financial_time)if financial_report is not None:return financial_report.iloc[0]['totalAssets'], financial_report.iloc[0]['EPS']return None, Nonedef get_stock_pool(self):"""选取哪些股票"""stock_code_list = QA.QA_fetch_stock_list_adv().code.tolist()the_financial_time = self.get_financial_time()for stock_code in stock_code_list:# print(stock_code)assets, EPS = self.get_assets_eps(stock_code, the_financial_time)if assets is not None and EPS != 0:data = QA.QA_fetch_stock_day_adv(stock_code, self.start_time, self.stop_time)if data is None:continueprice = data.to_pd().iloc[0]['close']if 0 < price / EPS < 20: # 满足条件才添加进行排序# print(price / EPS)self.stock_pool.append(stock_code)def cjlyz(self, data, n=20):# log(30日日均交易量/昨日交易量)data['cjlyz'] = 0data['n_days_vol_ave'] = QA.MA(data['volume'], n)data = data.fillna(0)last_index = 0for index, row in data.iterrows():if last_index != 0:data.loc[index, 'cjlyz'] = row['n_days_vol_ave'] / data.loc[last_index, 'volume']last_index = indexfor index, row in data.iterrows():if row['cjlyz'] != 0:data.loc[index, 'cjlyz'] = math.log10(row['cjlyz'])return data# 反转因子def fzyz(self, data, n=10, m=5):# (ma10-ma5)/ma5data['ma_10'] = QA.MA(data['close'], n)data['ma_5'] = QA.MA(data['close'], m)data['fzyz'] = (data['ma_10'] - data['ma_5']) / data['ma_5']data = data.fillna(0)return datadef get_EPS(self, stock_code, the_time):# 由财政数据中得到EPS,是上个季度的year = the_time[0:4]if_break = Falsen_EPS_list = []while (True):for day in self.time_quantum_list:date = year + dayif date < the_time:financial_report = QA.QA_fetch_financial_report(stock_code, date)if financial_report is not None:return financial_report.iloc[0]['EPS']if if_break: # 触发,则跳出循环breakyear = str(int(year) - 1)def three_para(self, data):# 整合三个因子data = self.cjlyz(data)data = self.fzyz(data)data['EPS'] = 0if_first = Truelast_index = Nonefor index, row in data.iterrows():if_value_equal = True # 值是否跟上次值相同the_time = str(index[0])[:10]if not if_first:last_time = str(last_index[0])[:10]for time_quantum in self.time_quantum_list:middle_time = last_time[:4] + time_quantum # 得到判断的分界点if last_time < middle_time < the_time: # 有一次处于分界点左右,则需要重新计算if_value_equal = Falsebreakif if_value_equal:data.loc[index, 'EPS'] = data.loc[last_index, 'EPS']if if_first or not if_value_equal:stock_code = str(index[1])# print(stock_code)value = self.get_EPS(stock_code, the_time)data.loc[index, 'EPS'] = valueif_first = Falselast_index = index # 把当次索引加入,下次调用则为上次索引data['decided_para'] = 0.3 * data['EPS'] + 0.4 * data['cjlyz'] + 0.3 * data['fzyz']return datadef solve_data(self):self.data = QA.QA_fetch_stock_day_adv(self.stock_pool, self.start_time, self.stop_time)self.ind = self.data.add_func(self.three_para)def run(self):self.solve_data()print(self.ind)for items in self.data.panel_gen:today_time = items.index[0][0]one_day_data = self.ind.loc[today_time] # 得到有包含因子的DataFrameone_day_data['date'] = items.index[0][0]one_day_data.reset_index(inplace=True)one_day_data.sort_values(by='decided_para', axis=0, ascending=False, inplace=True)today_stock = list(one_day_data.iloc[0:self.n_stock]['code'])one_day_data.set_index(['date', 'code'], inplace=True)one_day_data = QA.QA_DataStruct_Stock_day(one_day_data) # 转换格式,便于计算bought_stock_list = list(self.Account.hold.index)print("SELL:")for stock_code in bought_stock_list:# 如果直接在循环中对bought_stock_list操作,会跳过一些元素if stock_code not in today_stock:try:item = one_day_data.select_day(str(today_time)).select_code(stock_code)order = self.Account.send_order(code=stock_code,time=today_time,amount=self.Account.sell_available.get(stock_code, 0),towards=QA.ORDER_DIRECTION.SELL,price=0,order_model=QA.ORDER_MODEL.MARKET,amount_model=QA.AMOUNT_MODEL.BY_AMOUNT)self.Broker.receive_order(QA.QA_Event(order=order, market_data=item))trade_mes = self.Broker.query_orders(self.Account.account_cookie, 'filled')res = trade_mes.loc[order.account_cookie, order.realorder_id]order.trade(res.trade_id, res.trade_price, res.trade_amount, res.trade_time)except Exception as e:print(e)print('BUY:')for stock_code in today_stock:try:item = one_day_data.select_day(str(today_time)).select_code(stock_code)order = self.Account.send_order(code=stock_code,time=today_time,amount=1000,towards=QA.ORDER_DIRECTION.BUY,price=0,order_model=QA.ORDER_MODEL.CLOSE,amount_model=QA.AMOUNT_MODEL.BY_AMOUNT)self.Broker.receive_order(QA.QA_Event(order=order, market_data=item))trade_mes = self.Broker.query_orders(self.Account.account_cookie, 'filled')res = trade_mes.loc[order.account_cookie, order.realorder_id]order.trade(res.trade_id, res.trade_price, res.trade_amount, res.trade_time)except Exception as e:print(e)self.Account.settle()Risk = QA.QA_Risk(self.Account)print(Risk.message)# plt.show()Risk.assets.plot() # 总资产plt.show()Risk.benchmark_assets.plot() # 基准收益的资产plt.show()Risk.plot_assets_curve() # 两个合起来的对比图plt.show()Risk.plot_dailyhold() # 每只股票每天的买入量plt.show()start = time.time()
sss = ThreePara('2017-01-01', '2018-01-01', 10)
stop = time.time()
print(stop - start)
print(len(sss.stock_pool))
sss.run()
stop2 = time.time()
print(stop2 - stop)
[QUANTAXIS量化分析]三因素模型相关推荐
- [QUANTAXIS量化分析]羊驼策略1
羊驼策略1 基本原理 在本策略中,每天按照收益率从小到大对股票池中的所有股票进行排序,起始时买入num_of_stocks只股票,然后每天在整个股票池中选出收益率前num_of_stocks,如果这些 ...
- garch预测 python_【2019年度合辑】手把手教你用Python做股票量化分析
引言 不知不觉,2019年已接近尾声,Python金融量化公众号也有一年零两个月.公众号自设立以来,专注于分享Python在金融量化领域的应用,发布了四十余篇原创文章,超过两万人关注.这一路走来,有过 ...
- #让我们用python跑回归#Fama-French三因素模型(一)
先简单介绍一下尤金·法玛: 尤金·法玛(Eugene F. Fama),著名经济学家.金融经济学领域的思想家,芝加哥经济学派代表人物之一.芝加哥大学教授,2013年诺贝尔经济学奖得主. 1990年代初 ...
- python量化分析招聘_怎么准备国内量化分析师岗位的面试?
既然是面试,那么面试就有很多常规的准备工作,可以参考:面试前你都做了什么准备? - 知乎 对于量化分析师,有如下几点可以注意:岗位职责 招人肯定是希望能够干活,能干好活,所以你应该重视招聘内容里面的岗 ...
- python 量化分析 入门_【合辑·收藏】Python量化从入门到精通
原标题:[合辑·收藏]Python量化从入门到精通 引言 自2018年9月27日发第一篇推文以来,公众号"Python金融量化"专注于分享Python在金融量化领域的实战应用,坚持 ...
- TensorRT-8量化分析
TensorRT-8量化分析 本文讲非对称量化.量化方式等等一些细节,不过有一段时间在做基于TensorRT的量化,需要看下TensorRT的量化细节.这次文章是偏实践的一篇,主要过一下TensorR ...
- 从直觉主义到量化分析 让大数据做主
文章讲的是从直觉主义到量化分析 让大数据做主,还记得去年8·15电商竞争价格大战吗?如果你是某电商CEO,你还会采用这样的竞争战略吗?变化是永恒的主题,企业管理不能一成不变.在大数据时代,电商采用价格 ...
- 【Python金融量化 2- 100 】股票量化分析基本知识
Author:Runsen 文章目录 什么是股票 什么是量化分析 股票代码 K线图 tushare的抓取数据 pandas_datareader 什么是股票 股票(stock)是股份公司发行的所有权凭 ...
- 阿里云Lindorm联合智臾科技发布,金融高频交易数据量化分析与处理方案
简介:面向银行.保险.券商和私募的高频数据高性能一站式解决方案. 金融市场L1/L2的报价和交易数据是量化交易研究非常重要的数据,随着数字业务快速演进,具有时序特征的交易数据激增,对底层数据库和量化分 ...
最新文章
- HDU3434数学题
- Tensor for ‘out‘ is on CPU, Tensor for argument #1 ‘self‘ is on CPU
- 朴素贝叶斯分类器(Navie Bayesian Classifier)中的几个要点(一)
- java实现对properties类型文件的读写
- python课程设计
- html ul高度自适应,如何让div中的ul元素自适应
- Adobe AIR移动App的互相调用实现方式
- 调用 WebService 请求因 HTTP 状态 407 失败
- 还原真实的 cache recovery
- PyCharm中的一些设置
- MATLAB神经网络应用之Elman神经网络
- MIMOl信道估计基本原理
- linux 更新包缓存目录,清除ubuntu下缓存、软件安装包和多余内核
- analyze 命令
- 一文教你如何在Linux系统上搭建samba文件共享服务器
- 【2019.05】python 爬取拉钩数据(静态+动态)
- memcacheredis构建缓存服务器
- app 服务器维护通知,启用 App Store 服务器通知
- 基于Python和TensorFlow的AI作曲的设计与实现
- 什么是客户终身价值(LTV)