研报复现系列(一):【方正证券】跟踪聪明钱:从分钟行情数据到选股因子

1.研报概述

本文是研报复现系列的第一篇,文本复现了【方正证券】的研报【跟踪聪明钱:从分钟行情数据到选股因子】。

该研报尝试从分钟行情数据中挖掘出那些聪明人(即机构)所做的交易,称为“聪明钱”,并量化这些聪明钱对后市看涨、看跌的情绪观点,进而跟随聪明钱进行选股。

2.研究环境

JointQuant

import datetime
import math
import matplotlib.pyplot as plt
from jqdata import *
import pandas as pd
import numpy as np
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False 

3.研报复现

3.1 数据获取

本文数据来源于聚宽JoinQuant。用到的接口名和功能如下表所示。具体参数请查阅聚宽的API文档。

接口名功能
get_bars获取行情数据
get_price获取获取数据、是否停牌、涨跌停价
get_trade_days获取一段时间内的交易日列表
get_extras查询特定股票是否是ST股
get_all_securities获取股票数据,包括上市时间
get_index_stocks获取指数成分股

3.2 划分聪明钱

聪明钱在交易过程中往往呈现“单笔订单数量更大、订单报价更为激进”

因此,某分钟的交易的聪明度指标S定义为:S= ∣ R t ∣ \left| Rt \right| Rt / / / V t \sqrt{Vt} Vt

Rt为第t分钟的涨跌幅,Vt为第t分钟的成交量。S的值越大,则说明此交易越聪明。

我们封装一个获取分钟行情数据以及S值的函数,方便后面的研究使用。

def get_minute_data(security,#股票代码,可以是list或者字符串count,#获取多少条数据end_dt=datetime.datetime.now()
):
df = get_bars(security,
count = count,
include_now=True,
unit = '1m',
fields = ['date','open','close','volume'],
df = True,
end_dt = end_dt)df['R'] = (df['close'] - df['open'])/df['open']#涨跌幅
df['S'] = abs(df['R'])/df['volume']**0.5*10000 #S值,乘10000为了方便画图
df['volume'] = df['volume']/10000#volume除以10000方便画图
return df

原研报利用成交量与计算出的S值来划分聪明钱交易。

划分算法为:
step1:对于特定股票,特定时间段的分钟级交易数据,计算得到每分钟的S值,并将数据按照S值由大到小排序。
step2:求排序后的分钟数据的交易量累加和,将交易量累加和占该该时间段总成交量前20%的分钟交易视为由聪明钱进行的交易。

其中,阈值选取20%是因为在A股市场中机构交易者只贡献了少量的交易量,原研报同时测试了阈值选取其他数值时效果,其中20%是最优的.

我们以603198.XSHG在2021年4月8日下午14:00到14:30的分钟数据为例,给出划分聪明钱的程序并将结果可视化。

'''
功能:寻找聪明钱的交易并可视化
算法:对于特定的股票,特定时间段的分钟级交易数据,计算得到每分钟的S值,并将数据按照S值由大到小排序。求排序后的分钟数据的交易量累加,将交易量累加和占比前20%的分钟视为由聪明钱交易的时刻。其中,阈值选取20%是因为在A股市场中机构交易者只贡献了少量的交易量,原研报同时测试了阈值选取其他数值时效果,其中20%是最优的。
数据:以603198.XSHG在2021年4月8日下午14:00到14:30的分钟数据为例。
'''
#获取数据并且个每个分钟编号
df = get_minute_data('603198.XSHG',30,end_dt='2021-04-08 14:30:00')
df['bar_no'] = [_ for _ in range(1,31)]#每根bar的序号,方便x轴的显示#绘图
fig = plt.figure(figsize=(14,10))
#S值与成交量图
ax = fig.add_subplot(211)
h1 = ax.bar(df.index,df['volume'],label='成交量',width=0.5)#成交量
ax2 = ax.twinx()
h2 = ax2.scatter(df.index, df['S'],label='S因子',marker='o',color='r')#S值
plt.legend([h1,h2], [h1.get_label(),h2.get_label()], loc='best')
ax.grid()#网格
ax.set_ylabel(u"成交量(万)")
ax.set_title(u"成交量与S因子值")
ax2.set_ylabel(u"S值(10e-4)")
ax.set_xlabel(u"时间序号")
plt.xticks(df.index.values, df['bar_no'])#排序后的图
ax = fig.add_subplot(212)
df = df.sort_values(by='S',ascending=False).reset_index(drop=True)#按S值排序
df['acc_volume_pct'] = df['volume'].cumsum()/df['volume'].sum()#计算累计成交量
df1 = df[df['acc_volume_pct']<=0.2]#累计成交量前20%
df2 = df[df['acc_volume_pct']>0.2]
ax.bar(df1.index,df1['volume'],color='r',width=0.5)#绘制累计成交量前20%的柱状图
h1 = ax.bar(df2.index,df2['volume'],label='成交量',width=0.5)#绘制余下的
ax2 = ax.twinx()
h2 = ax2.plot(df.index, df['acc_volume_pct'],label='累计成交量占比',marker='o',color='g')#累计成交量
plt.legend([h1,h2[0]], [h1.get_label(),h2[0].get_label()], loc='best')
ax.grid()
ax.set_ylabel(u"成交量(万)")
ax.set_title(u"选择聪明钱")
ax2.set_ylabel(u"累计成交量")
ax.set_xlabel(u"时间序号")
plt.xticks(df.index.values, df['bar_no'])

图片

3.3 量化聪明钱对股票后市的情绪

我们划分出了聪明钱的交易后,如何判断聪明钱是对这只股票看多还是看空呢

对于特定股票、特定时段的分钟行情数据,按照上述方法划分出聪明钱的交易之后,我们可以构造聪明钱的情绪因子Q

Q = vwap_smart/vwap_all

vwap_smart和vwap_all分别是聪明钱的成交量加权平均价和该段时间内所有分钟的成交量加权平均价

因子 Q 实际上反映了在该时间段中聪明钱参与交易的相对价位。之所以将其称为聪明钱的情绪因子,是因为因子 Q 的值越大,表明聪明钱的交易越倾向于出现在价格较高处,这是逢高出货的表现,反映了聪明钱的看空,消极情绪;因子Q的值越小,则表明聪明钱的交易多出现在价格较低处,这是逢低吸筹的表现,看多,积极情绪。

我们将情绪因子Q的计算封装成一个函数

def calcQ(data_bar):'''功能:计算Q值参数:DataFrame类型,特定股票一定时间段内的分钟数据(close,volume和S)返回:浮点数,即Q值'''data_bar = data_bar.sort_values(by='S',ascending=False).reset_index(drop=True)#按S值排序data_bar['acc_volume_pct'] = data_bar['volume'].cumsum()/data_bar['volume'].sum()#计算累计成交量smart_bar = data_bar[data_bar['acc_volume_pct']<=0.2]#聪明钱交易,累计成交量前20%#vwmap:volume weighted average price,成交量加权平均价vwap_smart = (smart_bar['close']*smart_bar['volume']).sum()/smart_bar['volume'].sum()vwap_all = (data_bar['close']*data_bar['volume']).sum()/data_bar['volume'].sum()return vwap_smart/vwap_all

3.4因子选股能力验证

本小节对上一小节量化出的聪明钱情绪因子的选股能力进行验证。

样本空间:沪深300成分股,剔除 ST 股和上市未满 60 日的新股,以及涨停、停牌、跌停(原研报为全部A股,但数据量过多,受硬件限制本文缩小了样本范围,做了简化)

测试时间:2013-04-30 到 2016-05-31

测试方法:每个月末时,对于选股空间的所有股票,计算其之前10天的分钟级交易数据的Q值,和该股票次月的收益率。这样每个月可以得到两组序列,分别为每只股票的Q值和次月的收益率,计算其RankIC秩相关系数。可视化测试时间周期内所有月份的两组序列的相关系数,统计显著相关情况。

概念解释

RankIC秩相关系数为两组序列中的元素在序列中的相对位置(即大小顺序)的相关系数。

在因子模型中,因子与收益的相关系数大于0.03即认为是有效的因子。

为了实现对因子的验证,我们封装了两个简单的函数,分别用于

1.获取特定日期满足交易条件的股票(即在选股样本中剔除ST股、涨停、跌停等)

2.获取特定日期所在月的最后一日,用于获取次月的行情数据

def get_stocks(date,index=None):'''功能:根据日期,获取该日满足交易要求的股票相关数据,即剔除ST股、上市未满60天、停牌、跌涨停股参数:date,日期index,指数代码,在特定指数的成分股中选股。缺省时选股空间为全部A股返回:DataFrame类型,索引为股票代码,同时包含了价格数据,方便后续使用'''stocks = get_all_securities(types=['stock'],date=date)#该日正在上市的股票if index:#特定成分股stock_codes = get_index_stocks(index,date=date)#成分股stocks = stocks[stocks.index.isin(stock_codes)]#上市日期大于60个自然日#date = datetime.datetime.strptime(date,'%Y-%m-%d').date()stocks['datedelta'] = date - stocks['start_date']stocks = stocks[stocks['datedelta'] > datetime.timedelta(days=60)]#是否是ST股stocks['is_st'] = get_extras(info='is_st',security_list=list(stocks.index),count=1, end_date=date).T#涨停、跌停、停牌stocks_info = get_price(security = list(stocks.index),fields=['close','high','low','high_limit','low_limit','paused'],count=1,end_date=date,panel=False).set_index('code').drop('time',axis=1)stocks['price'] = stocks_info['close']#顺便保存价格,方便后续运算stocks['paused'] = stocks_info['paused'] == 1#是否停牌stocks['high_stop'] = stocks_info['high'] >= stocks_info['high_limit']#涨停stocks['low_stop'] = stocks_info['low'] <= stocks_info['low_limit']#跌停stocks = stocks[~(stocks['is_st'] | stocks['paused'] | stocks['high_stop'] | stocks['low_stop'])]   return stocks
def last_day_of_month(any_day):#获取某个日期所在月份的最后一天,方便在计算次月收益时获取次月的时间范围next_month = any_day.replace(day=28) + datetime.timedelta(days=4)  # this will never failreturn next_month - datetime.timedelta(days=next_month.day)

万事俱备,我们现在统计每个月份每只股票的Q值和次月收益率,并计算秩相关系数、可视化。

#获取交易日序列
trade_days = get_trade_days(start_date='2013-04-30', end_date='2016-05-31')
#存储结果
result={'months':[],#月份序列'stocks':[],#股票序列'Q':[],#Q值序列'return':[]#次月收益序列
}
days_count = len(trade_days)
for i,date in enumerate(trade_days):#遍历交易日if i == days_count-1:#如果是列表最后一个日期#可交易的股票stocks = get_stocks(trade_days[i],index='000300.XSHG')stocks_list = list(stocks.index)#每只股票下个月的价格next_month_bar = get_bars(stocks_list, count = 1, unit = '1M',fields = ['open','close'],df = True,include_now=True,end_dt = '2016-06-30')'''获取分钟数据,用来计算Q这里一次性获取所有股票的数据,来减少数据请求的次数,加速程序运行'''data = get_minute_data(stocks_list,2400,end_dt=trade_days[i]).reset_index(level=0). rename(columns={'level_0':'code'})data_groups = data.groupby('code')#分钟数据根据股票代码分组result['stocks']+=stocks_listresult['months']+=[trade_days[i].strftime('%Y-%m')]*stocks.shape[0]#依次计算每一只股票的Q值result['Q']+=[calcQ(data_bar) for name,data_bar in data_groups]result['return']+=list((next_month_bar['close']-next_month_bar['open'])/next_month_bar['open'])       break        if trade_days[i+1].month != trade_days[i].month:#每月的最后一个交易日stocks = get_stocks(trade_days[i],index='000300.XSHG')stocks_list = list(stocks.index)next_month_bar = get_bars(stocks_list, count = 1, unit = '1M',fields = ['open','close'],df = True,include_now = True,end_dt = last_day_of_month(trade_days[i+1]))data = get_minute_data(stocks_list,2400,end_dt=date).reset_index(level=0).rename(columns={'level_0':'code'})data_groups = data.groupby('code')result['stocks']+=stocks_listresult['months']+=[date.strftime('%Y-%m')]*stocks.shape[0]result['Q']+=[calcQ(data_bar) for name,data_bar in data_groups]result['return']+=list((next_month_bar['close']-next_month_bar['open'])/next_month_bar['open'])df = pd.DataFrame(result)
'''
因为该段程序需要运行的时间较长,所以将运行出的结果存储到文件中
之后的研究可以直接读取文件
'''
df.to_excel('result.xlsx')
result = pd.read_excel('result.xlsx').drop('stocks',axis=1)
result_group = result.groupby('months')
#存储月份和每月两个序列的秩相关系数
result_df = {'month':[],'RankIC':[]
}
for month,month_result in result_group:result_df['month'].append(month)result_df['RankIC'].append(month_result.corr(method='spearman')['Q']['return'])
#以0.03作为阈值来划分显著和不显著相关    
result_df = pd.DataFrame(result_df)
ic_plus = result_df[result_df['RankIC']>0.03]
ic_minus = result_df[result_df['RankIC']<-0.03]
ic_other = result_df[(result_df['RankIC']>=-0.03) &(result_df['RankIC']<=0.03)]
print('显著为负: ',ic_minus.shape[0])
print('显著为正: ',ic_plus.shape[0])
print('不显著:',ic_other.shape[0])#可视化
fig = plt.figure(figsize=(14,5))
ax1 = fig.add_subplot(111)
ax1.bar(ic_other.index, ic_other['RankIC'], align='center', width=0.5, color='pink')
ax1.bar(ic_plus.index, ic_plus['RankIC'], align='center', width=0.5, color='r')
ax1.bar(ic_minus.index, ic_minus['RankIC'], align='center', width=0.5, color='b')
ax1.set_ylabel(u"Rank IC")
ax1.set_title(u"因子 RankIC 的月度序列")
ax1.set_xlabel(u"时间" )
ax1.grid(axis='y')
plt.xticks(result_df.index, result_df['month'],ro

显著为负: 22

显著为正: 7

不显著: 8

图片

由结果来看,股票Q值与次月收益率在大部分时间显著为负,这也许上文在定义Q时的分析一致。Q值越大,聪明钱对该只股票看跌,聪明钱在高位抛售该股,该股次月的收益率下降。

3.5 选股策略的构建与回测

研究方法:每月月底将股票前10日分数数据的Q值排序、根据Q值由小到大等分为5类。每一类分别建仓,可视化每一类的收益情况。

研究结果:在策略运行的时间周期内,5类持仓的收益率具有单调性。即Q值小的组收益率大。这也可以由之前的分析解释,因为Q值小意味着聪明钱在低价吸入,聪明钱具有看多的情绪。

策略构建:基于研究结果,可构建两种策略。

一种是多空对冲策略,即做多第一组的股票。做空第五组的股票,进行对冲。该对冲策略在本文的回测中的收益率高于五组分别做多的收益,且最大回撤更低。在原研报的所有A股的样本中,对冲策略的收益率位于第一组和第三组之间,且最大回撤更低。

另一种是做多第一组的股票,但是要剔除前期涨幅过高的五分之一的样本,原研报将这种选股组合称为SMART组合。

回测规则:每月月底计算Q值、选股、调仓。等权重配置股票,即让每只股票的(价格*持有数)占总资产的比例相同。初始资金100万,交易费率0.003,选股空间、与上文相同。

为了方便回测,我们新建了一个仓位类,来对应每一组的账户。该类具有当前持有的股票列表、对应的价格、每只股票持有数量、现金、账户净值这些属性提供了更新价格、调整仓位的功能,并可以维护现金和账户净值。

class Position():'''为了方便回测,我们新建了一个仓位类,来对应每一组的账户。该类具有当前持有的股票列表、对应的价格、每只股票持有数量、现金、账户净值这些属性提供了更新价格、调整仓位的功能,并可以维护现金和账户净值'''def __init__(self,stocks=np.array([]),price=np.array([]),weight=np.array([]),cash=0):self.stocks = stocksself.price = priceself.weight = weightself.cash = cashif not self.stocks.size:self.net_value = self.cashelse:self.net_value = (self.weight*self.price).sum()+self.cashdef update_price(self,price):#传入一个价格序列,对应持有股票的最新价格for i,p in enumerate(price):if not np.isnan(p):self.price[i] = pself.net_value = (self.weight*self.price).sum()+self.cashdef change_position(self,new_stocks,price,commission):#更新仓位,传入筛选出的股票列表和对应的价格for i,stock in enumerate(self.stocks):#原有股票不在新列表中,需要卖出if stock not in new_stocks:self.cash+=self.price[i]*self.weight[i]*(1-commission)#计算每一只股票应持有的数量new_weight = self.net_value*0.99/len(new_stocks)/pricenew_weight = [int(_) for _ in new_weight]for i,stock in enumerate(self.stocks):#原有股票在新列表中,需要调整数量if stock in new_stocks:weight_chg = new_weight[list(new_stocks).index(stock)] - self.weight[i]self.cash -= self.price[i]*weight_chg\+ abs(self.price[i]*weight_chg)*commissionfor i,stock in enumerate(new_stocks):#新增股票,需要买入if stock not in new_stocks:self.cash -= price[i]*new_weight[i]*(1+commission)self.stocks = new_stockpsself.weight = new_weightself.price = priceself.net_value = (self.weight*self.price).sum()+self.cash

多空对冲策略回测

capital_base = 1000000 #初始资金
commission = 0.003     #交易费率
#五组仓位
position_dict = {1:Position(cash=capital_base),2:Position(cash=capital_base),3:Position(cash=capital_base),4:Position(cash=capital_base),5:Position(cash=capital_base)
}
#净值统计
net_value_dict = {'month':[],#时间1:[],#每一组每个月月末的净值序列2:[],3:[],4:[],5:[]
}
trade_days = get_trade_days(start_date='2013-04-30', end_date='2016-05-31')
days_count = len(trade_days)
for i,date in enumerate(trade_days):#遍历交易日if  i == days_count-1 or trade_days[i+1].month != trade_days[i].month:#print(trade_days[i])#可交易股票stocks = get_stocks(trade_days[i],index='000300.XSHG')stocks_list = list(stocks.index)#股票的前10天的分钟数据,并根据股票分组data = get_minute_data(stocks_list,2400,end_dt=trade_days[i]).reset_index(level=0).rename(columns={'level_0':'code'})data_groups = data.groupby('code')#计算每一只股票的Q值stocks['Q'] = [calcQ(data_bar) for name,data_bar in data_groups]#Q值排序stocks = stocks.sort_values(by='Q').reset_index()lens = stocks.shape[0]#根据Q值的大小等分为5组s_1 = stocks[stocks['Q'].isin(stocks['Q'][:int(0.2*lens)])].reset_index()s_2 = stocks[stocks['Q'].isin(stocks['Q'][int(0.2*lens):int(0.4*lens)])].reset_index()s_3 = stocks[stocks['Q'].isin(stocks['Q'][int(0.4*lens):int(0.6*lens)])].reset_index()s_4 = stocks[stocks['Q'].isin(stocks['Q'][int(0.6*lens):int(0.8*lens)])].reset_index()s_5 = stocks[stocks['Q'].isin(stocks['Q'][int(0.8*lens):])].reset_index()#如果有持仓数据if position_dict[1].stocks.size:#更新持仓价格for cls in range(1,6):position_dict[cls].update_price(price=get_price(                       security = list(position_dict[cls].stocks),count = 1,end_date = trade_days[i],panel = False)['close'])#调仓position_dict[1].change_position(new_stocks=s_1['index'],price = s_1['price'],commission=commission)            position_dict[2].change_position(new_stocks=s_2['index'],price = s_2['price'],commission=commission)position_dict[3].change_position(new_stocks=s_3['index'],price = s_3['price'],commission=commission)position_dict[4].change_position(new_stocks=s_4['index'],price = s_4['price'],commission=commission)position_dict[5].change_position(new_stocks=s_5['index'],price = s_5['price'],commission=commission)#添加该月的结果net_value_dict['month'].append(trade_days[i])for cls in range(1,6):net_value_dict[cls].append(position_dict[cls].net_value)continue#可视化
net_value_df = pd.DataFrame(net_value_dict)
net_value_df.to_excel('net_value_df.xlsx')
net_value_df = pd.DataFrame(net_value_dict)
plt.figure(figsize=(14,6))
net_value_df[1] = (net_value_df[1]/1000000)
net_value_df[2] = (net_value_df[2]/1000000)
net_value_df[3] = (net_value_df[3]/1000000)
net_value_df[4] = (net_value_df[4]/1000000)
net_value_df[5] = (net_value_df[5]/1000000)
net_value_df['1与5对冲'] = net_value_df[1] - net_value_df[5]+1
index=get_bars('000300.XSHG', count = 37, unit = '1M',fields = ['close'],df = True,include_now=True,end_dt = '2016-05-31')['close']
index = index/index[0]
fig = plt.figure(figsize=(14,5))
ax = fig.add_subplot(111)
ax.plot(net_value_df['month'].index,net_value_df[1],label='1组')
ax.plot(net_value_df['month'].index,net_value_df[2],label='2组')
ax.plot(net_value_df['month'].index,net_value_df[3],label='3组')
ax.plot(net_value_df['month'].index,net_value_df[4],label='4组')
ax.plot(net_value_df['month'].index,net_value_df[5],label='5组')
ax.plot(net_value_df['month'].index,net_value_df['1与5对冲'],label='1组与5组对冲',linestyle='--',linewidth=3)
ax.plot(net_value_df['month'].index,index,linestyle='--',label='沪深300',color='black',linewidth=3)
ax.set_xlabel(u"时间")
ax.set_ylabel(u"净值")
ax.set_title(u"分组表现与多空对冲净值")
plt.xticks(net_value_df['month'].index,net_value_df['month'],rotation=90)
plt.legend()

图片

SMART选股策略

capital_base = 1000000
position_dict_2 = {1:Position(cash=capital_base)
}
net_value_dict_2 = {'month':[],1:[]
}trade_days = get_trade_days(start_date='2013-04-30', end_date='2016-05-31')
days_count = len(trade_days)
commission = 0.003
for i in range(days_count):if i == days_count-1 or trade_days[i+1].month != trade_days[i].month:stocks = get_stocks(trade_days[i],index='000300.XSHG')stocks_list = list(stocks.index)data = get_minute_data(stocks_list,2400,end_dt=trade_days[i]).reset_index(level=0).rename(columns={'level_0':'code'})data_groups = data.groupby('code')stocks['Q'] = [calcQ(data_bar) for name,data_bar in data_groups]stocks = stocks.sort_values(by='Q').reset_index()lens = stocks.shape[0]s_1 = stocks[stocks['Q'].isin(stocks['Q'][:int(0.2*lens)])].reset_index(drop=True)month_bar = get_bars(list(s_1['index']), count = 1, unit = '1M',fields = ['open','close'],df = True,include_now=True,end_dt = trade_days[i]).reset_index(drop=True)#剔除涨幅过高的20%的股票s_1['ratio'] = (month_bar['close'] - month_bar['open'])/month_bar['open']s_1 = s_1.sort_values(by='ratio').reset_index(drop=True)lens = s_1.shape[0]s_1 = s_1[s_1['ratio'].isin(s_1['ratio'][:int(0.8*lens)])]if position_dict_2[1].stocks.size:position_dict_2[1].update_price(price=get_price(                       security = list(position_dict_2[1].stocks),count = 1,end_date = trade_days[i],panel = False)['close'])position_dict_2[1].change_position(new_stocks=s_1['index'],price = s_1['price'],commission=commission)            net_value_dict_2['month'].append(trade_days[i])net_value_dict_2[1].append(position_dict_2[1].net_value)#可视化
net_value_df_2 = pd.DataFrame(net_value_dict_2)
net_value_df_2[1] = (net_value_df_2[1]/1000000)
index=get_bars('000300.XSHG', count = 37, unit = '1M',fields = ['close'],df = True,include_now=True,end_dt = '2016-05-31')['close']
index = index/index[0]
fig=plt.figure(figsize=(14,5))
ax = fig.add_subplot(111)
ax.plot(net_value_df_2['month'].index,net_value_df_2[1],label='SMART选股组合')
ax.plot(net_value_df_2['month'].index,index,label='沪深300')
ax.set_xlabel(u"时间")
ax.set_ylabel(u"净值")
ax.set_title(u"SMART选股组合")
plt.xticks(net_value_df_2['month'].index,net_value_df['month'],rotation=90)
plt.legend()

图片

4.总结

本文基本复现了【方正证券-跟踪聪明钱:从分钟行情数据到选股因子】的研究内容,同时得到了与原研报相近的结果。

本文的不足:

1.因为软硬件条件的限制,压缩了原研报的样本空间。

2.缺少原研报中因子风险特性的研究。

5.本文作者

蔡金航 哈尔滨工业大学威海校区 计算机科学与技术学院

舒意茗 哈尔滨工业大学威海校区 汽车工程学院

写在最后

我们是国内普通高校的在校学生,同时也是量化投资的初学者。我们的学校不是清北复交,也没有金融工程实验室,同时地处三线小城,因此我们在校期间较难获得量化实习机会,但我们期待与业界进行沟通、交流。

蔡金航同学是我们其中的一员。其在寻找暑期量化实习时,收到了几家私募和券商金工组的笔试邀请,笔试内容皆为在给定时间内复现出一篇金工研报。蔡同学受到启发,发觉复现金工研报是我们学习量化策略、锻炼程序设计能力同时也是与业界交流的很好的途径。

在蔡同学的建议下,我们开启研报复现系列的创作,记录我们的学习过程,并将我们的创作内容分享出来,与读者们一起交流、学习、进步。

我们的水平有限,创作的内容难免会有错误或不严谨的内容,我们欢迎读者的批评指正。

如果您对我们的内容感兴趣,请联系我们:cai_jinhang@foxmail.com

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/42647.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

中智股份冲刺上交所上市:半年收入约87亿元,计划募资37亿元

近日&#xff0c;中智经济技术合作股份有限公司&#xff08;下称“中智股份”&#xff09;预披露招股书&#xff0c;准备在上海证券交易所主板上市&#xff0c;中信证券为其保荐机构。 本次冲刺上市&#xff0c;中智经济计划募资37.42亿元&#xff0c;将用于中智人力资源研发运…

量化交易分析:4000多只股票2015-2022年历史数据分享,供小伙伴们学习交流

量化交易学习数据 下面是我在学习量化交易过程中自行保存的4000多只股票的基本数据&#xff0c;数据时间是从2015年1月–2022年9月&#xff0c;每只股票数据为一个.csv文件&#xff0c;包括每天开盘价、收盘价、最高价、最低价、成交量、成交额等数据&#xff0c;提供给需要的…

新增每日个股涨停原因及概念题材统计!股票量化分析工具QTYX-V2.6.6

功能概述 目前A股市场主旋律仍然是以行业及题材板块的热点轮动为主&#xff0c;因此从某种意义上来说&#xff0c;板块的强弱决定了选出个股的强弱。 我们的股票量化分析工具QTYX目前已经支持了统计行业板块内涨停板数量功能。‍ 为了进一步分析出市场上启动的热点概念题材。我…

证券服务应用评测系列:海通e海通财发布9.0版本,探索证券APP持续提升用户体验

易观分析&#xff1a;APP作为券商机构线上服务的入口&#xff0c;其活跃用户规模和运营水平在一定程度上能够体现机构战略定位、品牌运营、科技创新、用户竞争等综合实力。易观分析认为&#xff0c;如何围绕用户进行创新&#xff0c;利用技术将壁垒升高&#xff0c;打造具有品牌…

联合证券|再创纪录,外资狂买超1000亿!券商、期货板块持续活跃

A股今天全线上扬&#xff0c;沪指小幅走高&#xff0c;创业板、科创50指数体现强势&#xff1b;港股走势疲弱&#xff0c;恒生科技指数一度跌超2%。 详细来看&#xff0c;两市股指盘中震动上扬&#xff0c;午后全线走高&#xff0c;创业板指、科创50指数涨超1%&#xff1b;到收…

Excel根据出生日期获取真实年龄

说明 如果今天是 2021年01月22日 A的生日是2000年01月20日&#xff0c;B的生日是2000年01月23日 那么&#xff0c; A的真实年龄为21&#xff0c;B的真实年龄为20 Excel公式 使用函数 TODAY() //当前时间YEAR() //返回当前年MONTH() //返回当前月IF(条件&#xff0c;条件成立…

Excel计算出生日期、年龄、性别等身份相关的函数公式

在Excel的使用过程中&#xff0c;经常会遇到通过身份证号码提取出生日期、年龄、性别等操作&#xff0c;通过Excel的函数功能&#xff0c;能够比较容易地实现这些参数的提取。 1.事先准备 运行软件&#xff1a;Microsoft Office Excel 或 WPS Office Excel 等&#xff1b; 将…

【日积月累】出生日期如何转换成年龄进行显示

目录 一、数据库字段 二、 后端JavaBean字段 三、前端表格年龄展示 一、数据库字段 depart_birthday datetime NULL DEFAULT NULL COMMENT 员工出生日期, 二、 后端JavaBean字段 JsonFormat 设置格式化 JsonFormat(pattern "yyyy-MM-dd HH:mm:ss", timezone &q…

输入年龄显示今年多少岁

<script>var ageprompt("请输入你的年龄")var a1(你的年龄为age岁)alert(a1)</script> 输入 输出

python之通过身份证号码得出年龄、性别、地区

身份证号包含哪些信息? 行政区代码出生年月日同年同月同日的顺序编号性别校验码通过身份证得出地区、年龄性别、真假行政区代码 前6位是地址码,包含所在的省、市、区 出生年月日 第7到第14位表示出生年月日 例如19980822代表生日为1998年8月22 同年同月同日的顺序编号 …

人脸性别和年龄识别

本文是对age-gender-estimation项目的详细讲解&#xff0c;它给出了使用keras进行性别和年龄识别的完整流程。 数据 采用的数据集为imdb-wiki&#xff0c;这是一个包含 20,284名人的460,723张以及维基百科上imdb的 62,328张共计523,051 张人脸图像的数据集&#xff0c;是目前…

chatgpt赋能python:Python如何计算年龄?

Python如何计算年龄&#xff1f; 计算年龄是一项常见的任务&#xff0c;尤其在与生物、医学或保险有关的领域。在Python中&#xff0c;计算年龄可以通过各种方式实现。在本文中&#xff0c;我们将探讨如何使用Python计算年龄。 Date函数 Python具有内置的Date函数&#xff0…

输入年龄,判断年龄阶段

#include<stdio.h> int main() { int age; printf("age:"); scanf("%d",&age); if(age>12&&age<18) printf("青少年"); else if(age>18&&age<60) printf("壮年");…

年龄识别之AgeNet

论文&#xff1a;AgeNet: Deeply Learned Regressor and Classifier for Robust Apparent Age Estimation ICCV2015 论文提出了一种基于人脸的年龄识别网络AgeNet。该网络同时基于分类和回归对年龄进行预测&#xff0c;然后将2个分支的特征进行融合&#xff0c;得到更好的预测…

chatgpt赋能python:Python年龄换算:如何根据Python版本算出“年龄”?

Python年龄换算&#xff1a;如何根据Python版本算出“年龄”&#xff1f; Python是一种高级编程语言&#xff0c;享有强大、易读、易用和可扩展性等各种优点。它是许多开发者使用的首选语言&#xff0c;尤其在数据科学和机器学习领域中备受推崇。 但是&#xff0c;Python几乎…

音视频技术开发周刊 | 301

每周一期&#xff0c;纵览音视频技术领域的干货。 新闻投稿&#xff1a;contributelivevideostack.com。 微软、谷歌、亚马逊&#xff0c;打响大模型时代的云战争 过去数月&#xff0c;云巨头们砸下真金白银&#xff0c;研发大模型、战略投资、自研 AI 芯片……大模型的时代方兴…

chatgpt如何引入本地知识?我们来看下emnlp 2022如何将本地图谱知识引入到任务型对话系统中

一、概述 title&#xff1a;Injecting Domain Knowledge in Language Models for Task-Oriented Dialogue Systems 论文地址&#xff1a;https://arxiv.org/abs/2212.08120 代码&#xff1a;GitHub - amazon-science/domain-knowledge-injection 1.1 Motivation 如何在PLM…

SpeechSynthesisUtterance实现语音播报

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>语音播报</title></head><body>&l…

Android TTS语音播报实践

在工作中遇到了语音播报的需求&#xff0c;在收到push后&#xff0c;用语音播报push携带的播报内容。类似于微信支付宝的收款信息一样。调研后主要的语音播报方案有一下几种&#xff1a; 基于第三方的TTS SDK&#xff0c;如百度、思必驰、讯飞等&#xff1b;自研Native的TTS引…

感谢ChatGPT,救了我狗的命!

前一段时间&#xff0c;国外一位小哥哥在推特上发布了一条消息&#xff0c;声称GPT-4拯救了自家狗狗的性命。 这是怎么一回事呢&#xff1f; 这个小哥哥养了一只两岁的边境牧羊犬&#xff0c;这只牧羊犬被诊断出患有蜱传疾病&#xff0c;这属于一种细菌性传染病。 虽然小哥哥一…