我们第一次买卖股票时,可能无从下手,因为不知道未来会怎样,所以对我们来说买多或买空的成功概率都是一样的。怎么办?反正都一样,那就抛硬币吧!是正面就买多,是背面就买空。港股虽然不允许直接买空,但是可以操作牛熊证,如果不喜欢牛熊证和涡轮,就可以选择不买,其实不买也是变相的买空,也就是说等它下跌到一定程度后再买入。这样通过抛硬币来决定买或不买的好处在哪里呢?从本质上说,只会给证券公司送佣金,捞不到半点好处,但是美国《旧金山纪事报》却通过做类似的事情盈利了,是怎么做到的呢?

他们是这样用大猩猩做选股实验的:他们让大猩猩随机选择写有股票代码的纸板,一共选择了5只股票,然后用大猩猩挑选的股票组合与《华尔街日报》中8位知名分析师挑选的5只股票相比较,在持有一段时间后,大猩猩随机抽取的股票的票面价值竟超过职业分析师选择的股票的票面价值。表面上看这似乎不太可能,感觉大猩猩运气太好了,但是后来人们在相继的操作中发现一个关键细节,那就是定期卖掉所持有的股票中收益率最差的一只,再让大猩猩随机选择一只股票来买。

也许有人会说,这太不靠谱了,股票价格上涨最关键的因素是企业的收益率,收益率上涨,股票价格一定上涨。

也有人认为大盘指数才是最关键的因素,大盘指数上涨,股票价格一定上涨,毕竟大盘指数是由众多个股决定的。

还有人认为股票价格应该受到资本资产的影响,可以根据资本资产的关系进行定价,也就是所谓的资本资产定价模型。
这时候财务人员说,什么都不如财务指标好使,财务指标才是最忠诚的伙伴。

大家各不相让,每个人都据理力争,最终也没有结果。既然大猩猩随机选股的效果都那么好,那么就按照每个人的理解,各自加入一个或多个因素,然后也像大猩猩那样不断地轮换吧!
于是大家都同意这个办法,各自确定其关键因素去了。这里就用财务的一些因素来看一下,多因素(多因子)模型应该如果选股。其实单单就财务数据而言,影响股价变动的因素就有很多,如图:

引入数据:引入公司10年以上的历史财务数据、股票10年以上的历史数据和实时行情数据。 买入条件:
(1)根据财务因子进行不同的多因子组合,从单一因子到几十个因子,这种组合可能有成千上万个,不过没关系,我们就把每一个组合当成一个进程;
(2)随机选择50只股票进行买入;
(3)一个月后将表现最不好的10只股票剔除,被剔除的股票不再选择;
(4)不断地循环上述过程,直至历史数据全部遍历完;
(5)将总的收益与大盘指数进行比较,看看是否有超额收益;
(6)如果有超额收益,则可以进入模拟交易进行测试。
经验:关于多因子的组合,不仅是一个阶乘那么简单,还可以把不同的财务数据进行对比,得出新的因子。
今天给大家分享一个简单的策略—— QMT 多因子选股策略 代码是基于 QMT 平台开发的量化选股策略,主要针对沪深 300 成分股进行多因子选股和定期调仓。策略结合了技术指标 (ATR 和 ADTM) 进行选股评分,并通过因子加权方式确定买入标的。
coding:gbk"""回测模型示例(非实盘交易策略)#HS300日线下运行,20个交易日进行 一次调仓,每次买入在买入备选中因子评分前10的股票,每支股票各分配当前可用资金的10%(权重可调整)#扩展数据需要在补完HS300成分股数据之后生成,本模型中扩展数据暂时使用VBA指标ATR和ADTM生成,命名为atr和adtm"""import pandas as pdimport numpy as npimport timeimport datetimedef init(ContextInfo): ContextInfo.s = ContextInfo.get_sector('000300.SH') ContextInfo.set_universe(ContextInfo.s) ContextInfo.day = 0 ContextInfo.holdings = {i:0 for i in ContextInfo.s} ContextInfo.weight = [0.1]*10 #设置资金分配权重 ContextInfo.buypoint = {} ContextInfo.money = ContextInfo.capital ContextInfo.profit = 0 ContextInfo.accountID='testS'def handlebar(ContextInfo): rank1 = {} rank2 = {} rank_total = {} tmp_stock = {} d = ContextInfo.barpos price = ContextInfo.get_history_data(1,'1d','open',3)if d > 60 and d % 20 == 0: #每月一调仓 nowDate = timetag_to_datetime(ContextInfo.get_bar_timetag(d),'%Y%m%d')print(nowDate) buys, sells = signal(ContextInfo) order = {}for k in list(buys.keys()):if buys[k] == 1: rank1[k] = ext_data_rank('atr',k[-2:]+k[0:6],0,ContextInfo) rank2[k] = ext_data_rank('adtm',k[-2:]+k[0:6],0,ContextInfo)#print rank1[k], rank2[k] rank_total[k] = 1.0 * rank1[k] #因子的权重需要人为设置,此处取了0.5和-0.5print (1111111, rank1[k]) tmp = sorted(list(rank_total.items()), key = lambda item:item[1])#print tmpif len(tmp) >= 10: tmp_stock = {i[0] for i in tmp[:10]}else: tmp_stock = {i[0] for i in tmp} #买入备选中若超过10只股票则选10支,不足10支则全选for k in list(buys.keys()):if k not in tmp_stock: buys[k] = 0if tmp_stock:print('stock pool:',tmp_stock)for k in ContextInfo.s:if ContextInfo.holdings[k] > 0 and sells[k] == 1:print('ready to sell') order_shares(k,-ContextInfo.holdings[k]*100,'fix',price[k][-1],ContextInfo,ContextInfo.accountID) ContextInfo.money += price[k][-1] * ContextInfo.holdings[k] * 100 - 0.0003*ContextInfo.holdings[k]*100*price[k][-1] #手续费按万三设定 ContextInfo.profit += (price[k][-1]-ContextInfo.buypoint[k]) * ContextInfo.holdings[k] * 100 - 0.0003*ContextInfo.holdings[k]*100*price[k][-1]#print price[k][-1]print(k)#print ContextInfo.money ContextInfo.holdings[k] = 0 ContextInfo.money_distribution = {k:i*ContextInfo.money for (k,i) in zip(tmp_stock,ContextInfo.weight)}for k in tmp_stock:if ContextInfo.holdings[k] == 0 and buys[k] == 1:print('ready to buy') order[k] = int(ContextInfo.money_distribution[k]/(price[k][-1]))/100 order_shares(k,order[k]*100,'fix',price[k][-1],ContextInfo,ContextInfo.accountID) ContextInfo.buypoint[k] = price[k][-1] ContextInfo.money -= price[k][-1] * order[k] * 100 - 0.0003*order[k]*100*price[k][-1] ContextInfo.profit -= 0.0003*order[k]*100*price[k][-1]print(k) ContextInfo.holdings[k] = order[k]print(ContextInfo.money,ContextInfo.profit,ContextInfo.capital) profit = ContextInfo.profit/ContextInfo.capitalif not ContextInfo.do_back_test: ContextInfo.paint('profit_ratio', profit, -1, 0)def signal(ContextInfo): buy = {i:0 for i in ContextInfo.s} sell = {i:0 for i in ContextInfo.s} data_high = ContextInfo.get_history_data(22,'1d','high',3) data_high_pre = ContextInfo.get_history_data(2,'1d','high',3) data_close60 = ContextInfo.get_history_data(62,'1d','close',3)#print data_high#print data_close#print data_close60for k in ContextInfo.s:if k in data_close60:if len(data_high_pre[k]) == 2 and len(data_high[k]) == 22 and len(data_close60[k]) == 62:if data_high_pre[k][-2] > max(data_high[k][:-2]): buy[k] = 1 #超过20日最高价,加入买入备选elif data_high_pre[k][-2] < np.mean(data_close60[k][:-2]): sell[k] = 1 #低于60日均线,加入卖出备选#print buy#print sellreturn buy,sell #买入卖出备选标的池:沪深300成分股
调仓频率:每20个交易日(约每月)调仓一次
选股规则:买入突破20日高点的股票,卖出跌破60日均线的股票
选股数量:每次买入10只股票(如果符合条件的股票≥10只)
资金分配:每只股票分配10%的可用资金(等权重分配)
因子排序:使用ATR和ADTM两个技术指标对股票进行排序
1、 init() 初始化函数
获取沪深300成分股列表- 初始化持仓字典(全为0)- 设置10只股票各10%的权重- 初始化账户资金和收益2、handlebar() 主处理函数
if 调仓日(d>60且每20天): 1. 生成买卖信号(signal函数) 2. 对买入备选股票按因子排序: rank1 = ATR指标排名 rank2 = ADTM指标排名 rank_total = 1.0 * rank1 # 实际只用了ATR排名 3. 选取排名前10的股票(或全部) 4. 执行卖出: - 持仓股票且卖出信号=1 - 市价卖出全部持仓 - 更新可用资金和累计收益 5. 执行买入: - 计算每只股票分配的资金 - 市价买入计算的数量 - 更新成本价和持仓 6. 计算并绘制收益率曲线买入条件(buy[k] = 1):前一天的最高价 > 过去20日的最高价(排除最近两天)即:突破20日高点卖出条件(sell[k] = 1):前一天的最高价 < 过去60日的收盘价均值(排除最近一天)即:跌破60日均线(1)开户成功后入金10万后提交QMT申请流程
(2)申请过程全程线上,预计2个工作日申请完成。
(3)等待开通过程中,可以提供测试账号、安装配置流程、量化会员资料。
(4)开通成功后,会通过邮件发送你软件下载地址,登录账号后就可以使用。

福利1:惊喜佣金
福利2:领取完整教程
福利3:添加量化讨论群
福利4:提供专业量化问题解答
福利5:量化工具安装使用教程、视频
福利6:极速柜台,量化投资者专用,速度微秒级
福利7:提供服务器托管模式:ptrade策略+ldp极速柜台+vip定向服务器(限50人)

