用机器学习像巴菲特一样投资
在股市交易中,有很多不同的方法可以找到合适的股票。现在已经出现了很多用来检测哪支股票值得投资的分析方法。比如:
● 技术分析:通过确定价格随着时间推移的走势来监测这些模式是否再次出现。
● 情绪分析:基于公众对某一特定股票的总体感觉或态度分析股票的可能走势。如果大众不看好这只股票,那么股票就会下跌。如果大众对某一支股票的评价非常积极,那么股票就涨势无限。
● 基本面分析:通过检查公司的资产负债表或现金流量表来确定公司的财务状态,从而进一步确定公司的价值对应当前的股价是否合理。
这些是最受欢迎的几种股票分析方法,但绝不是目前仅有的。
沃伦巴菲特被认为是世界上最成功的投资者之一,而他是基本面分析的大力拥趸者。如果世界上最成功的投资者之一都使用这一策略,也许我们都应该学习一下。然而,并不是所有人都有耐心和时间来学习基本面分析,去和那些报表打交道。那如果我们能通过机器学习来找出决定一支股票该不该买的几个关键指标,就能节省很多时间,更有针对性。
分类在机器中的应用
机器学习大显身手的时候来了。我们可以运用一个ML分类器来确定股票是该买入、卖出还是继续持有。为了确定一只股票或一家公司是否属于这三个类别之一,每家公司的季度报告都会被严格审查。因为这些季度报告会包含必要的财务信息,我们可以通过一些数据科学的方法来筛选重要的关键指标。
基本数据-季度报告
为了训练分类模型,我们需要收集大量的季度报告。Stockpup.com网站上有许多公司的季度报告历史记录,并可以方便的以CSV或Excel格式下载。但是,你到底应该下载多少季度报告呢?答案是越多越好。即使网站上列出的一些公司已经不存在了,也并不意味着它们过往的季报毫无用处。我们仍然可以在训练分类模型时利用这些数据。
检查季度报告
一旦我们下载了必要的基础数据(季度报告),我们就可以使用Python中的Pandas数据框来查看数据的格式了:
现在我们就可以观察每一列的数据和与之对应的日期了。我们先来看一下Price、Price High和Price Low列。这些信息通常不在季度报告中,但Stockpup.com网站为我们提供了这一有价值的信息,因为这三列数据这对我们判断股票应该买入、持有还是卖出非常重要。
现在,有很多种方法来决定一只股票是否值得投资。如果资产在三个季度内持续增加,负债在三个季度内持续减少,我们是否可以将其归类为买入?如果股票增加,长期债务减少呢?其实我们有很多种归类方式来确定某只股票应该归属的类别。
定义基本面分析方法
但如上文所说,我们如何在不了解如何进行基本面分析方法的情况下来简单的分析这些季度报告呢?既然我们不像股神巴菲特那样是基础理论专家,那就让我们用数据分析的方法来简化它吧:
- 首先根据所选季度的季度报告,观察从上一个季度到当前所选季度的变化情况。
- 然后,观察下一季度报告中的股价,看看股价是否有明显的上涨。
- 最后,根据季报中显示的变化和未来股价的走势,来确定它是买入、持有还是卖出。
从本质上来说,我们是在监测从上一季度到本季度的基本数据变化是否会影响未来的股票价格。我们将对每一季报相对于上一季报的表现进行判断,然后观察未来的股价。下面的图表也给我们表现了这个过程:
我们将把这种分析方法应用到每个季度报告中,以创建新的基本数据。这种方法将帮我们确定一支股票在某季度是否值得投资。显然,我们无法在第一个季度报告或最新的季度报告中使用这种方法,因为分析首先需要本季度和上一季度的报告。
清理和规范数据
创建类别标签
为了能够对每一份季度报告进行分类,我们需要定义一些分类规则。为了避免把事情搞得太复杂,我们可以简单地规定如果股价在下个季度大幅上涨,那就是买入。如果下跌,那就是卖出。如果两者都没有发生,那就持有股票继续观望。
以下是我们对每个季度报告的具体分类要求:
买入:在下个季度,price high和price low涨幅达到3%或更多。
卖出:在下个季度,price high和price low跌幅达到3%或更多。
持有:如果以上两种情况都没有发生。
我们还可以考虑其他可能的情况,但为了不让事情复杂化,让我们先保持这些简单的条件不变。
季报数据
如前所述,我们将会根据两份季报中的基本面数据来创造新的变量:当季的季报相对于上一个季度季报的变化百分比。
比如说在上一季度,股票的价值是1000英镑。然后在本季度,股价现在显示为1100英镑,增长了10%。那在本季度,我们就会用10%来代替那1100美元的股票实价。
我们对每一份季报个季度都执行这个过程(除了第一个季度,因为我们无法将它与前面不存在的季度进行比较)。如此一来,我们便可以得到每一份季报,依据每一个基本面数据所对应的变化百分比。
数据导入
现在,我们已经将季度数据格式化为百分比变化,并标记为买入、持有或卖出,我们就可以进行编程过程的展示了:
导入库和数据集
# Pandas in order to view and format the data import pandas as pd # Pandas option so we can see all rows and columns pd.set_option('display.max_rows', 200) pd.set_option('display.max_columns', 70) # Numpy for necessary calculations import numpy as np # Jupyter widget progress bar from tqdm import tqdm_notebook as tqdm # Pickle to import and export the formatted datasets import _pickle as pickle # Loading a pickle file that contains a dictionary with the keys being stock tickers and values being a DataFrame of QRs with open("stockpup.pkl",'rb') as fp: stocks_df = pickle.load(fp)
这个pickle文件不会在Github上被找到
Pickle 文件是一个包含了Stockpup.com上能找到的每个公司或股票的数据集。
用Helper Function进行预处理。
def setting_index(df): """ Returns a sorted datetime index """ df['Quarter end'] = pd.to_datetime(df['Quarter end']) df.set_index("Quarter end", inplace=True) return df.sort_index(ascending=True) def class_creation(df, thres=3): """ Creates classes of: - buy(1) - hold(2) - sell(0) Threshold can be changed to fit whatever price percentage change is desired """ if df['Price high'] >= thres and df['Price low'] >= thres: # Buys return 1 elif df['Price high'] <= -thres and df['Price low'] <= -thres: # Sells return 0 else: # Holds return 2
接下来会继续用这些函数
对每支股票进行数据变形
# Setting the index as the Datefor i in tqdm(stocks_df.keys()): stocks_df[i] = setting_index(stocks_df[i]) # Replacing all "None" values with NaNfor i in tqdm(stocks_df.keys()): stocks_df[i].replace("None", 0, inplace=True) # Creating a new dictionary that contains the numerical values, then converting all values to numeric valuesnum_df = {}for i in tqdm(stocks_df.keys()): num_df[i] = stocks_df[i].apply(pd.to_numeric) # Replacing values with percent difference or changepcnt_df = {}for i in tqdm(num_df.keys()): pcnt_df[i] = num_df[i].pct_change(periods=1).apply(lambda x: x*100) # Replacing infinite values with NaNfor i in tqdm(pcnt_df.keys()): pcnt_df[i] = pcnt_df[i].replace([np.inf, -np.inf], np.nan) # Creating a new DataFrame that contains the class 'Decision' determining if a quarterly reports improvement is a buy, hold, or sell.new_df = {}for i in tqdm(pcnt_df.keys()): # Assigning the new DF new_df[i] = pcnt_df[i] # Creating the new column with the classes, shifted by -1 in order to know if the prices will increase/decrease in the next quarter. new_df[i]['Decision'] = new_df[i].apply(class_creation, axis=1).shift(-1) # Excluding the first and last rowsfor i in tqdm(new_df.keys()): new_df[i] = new_df[i][1:-1] # Combining all stock DFs into onebig_df = pd.DataFrame()for i in tqdm(pcnt_df.keys()): big_df = big_df.append(new_df[i], sort=False) # Filling the NaNs with 0big_df.fillna(0, inplace=True)# Resetting the index because we no longer need the datesbig_df.reset_index(drop=True, inplace=True)# Dropping the price related columns to prevent data leakagebig_df.drop(['Price', 'Price high', 'Price low'], 1, inplace=True)# Exporting the final DataFramewith open("main_df.pkl", 'wb') as fp: pickle.dump(big_df, fp)
值得注意的几点是:
●数据中的第一行和最后一行被排除掉是因为第一行无法显示变化,而最后一行也因为没有下一季度的数据所以无法计算价格变化。
●数据需要进行合并以便之后训练我们的分类模型。
●数据表中的索引被重置,因为我们不再需要日期这一信息。 现在,每行的季度报告都包含来自过去和将来的季度报告信息,因此日期对于模型不再重要。
●与价格相关的变量被删除,以防止数据泄漏。
最后,我们把基本数据转换成了正确的格式和我们想要的样子。然后我们导出最终的数据表以进行数据探索并训练分类模型。
探索数据
接下来,为了更加熟悉我们的数据,我们需要进行一些简单的探索性数据分析。这样做是为了更好地理解我们的数据,并确保在转换数据时不会遗漏任何问题。因此,让我们开始使用一些代码进行数据的可视化。
运用Import将数据导入和加载到我们先前创建的数据框架中
import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns import _pickle as pickle # Opening the .pkl file created with open("main_df.pkl",'rb') as fp: final_df = pickle.load(fp)
可视化每个类别的数量
# Separating each class into respective DataFrames buy_df = final_df[final_df['Decision']==1].loc[:, final_df.columns != 'Decision'].reset_index(drop=True) hold_df = final_df[final_df['Decision']==2].loc[:, final_df.columns != 'Decision'].reset_index(drop=True) sell_df = final_df[final_df['Decision']==0].loc[:, final_df.columns != 'Decision'].reset_index(drop=True) # Visualizing in matplotlib plt.figure(figsize=(10,6)) plt.style.use('fivethirtyeight') # Plotting the count of each DataFrame of each class plt.bar("Buy", buy_df.shape[0]) plt.bar("Sell", sell_df.shape[0]) plt.bar("Hold", hold_df.shape[0]) plt.ylabel("# of Quarterly Reports") plt.title('Count of Quarterly Reports') plt.show()
这段代码会为我们显示每个类别的数量分布图表
下图显示了每个类别中的数量
看到这里,你可能已经发现了,我们的数据在三个类别下存在分布不平衡的情况。这可能会造成问题。但是我们又不想丢弃掉数据点,因为如果我们选择去掉一些数据,每个类别的数量将会等于数量最少的那个类别的数量。即使这可能是解决类别数据分布失衡的可行方案,我们也可以探索其他选择。另一种方案是在验证我们的分类模型时使用不同的评估指标。
数据中的相关性
def CorrMtx(df, dropDuplicates = True): """ Takes in a Correlation DF and excludes nonessential visuals. Creates a more visually pleasing correlation matrix """ # Exclude duplicate correlations by masking uper right values if dropDuplicates: mask = np.zeros_like(df, dtype=np.bool) mask[np.triu_indices_from(mask)] = True # Set background color / chart style sns.set_style(style = 'white') # Set up matplotlib figure f, ax = plt.subplots(figsize=(11, 9)) # Add diverging colormap from red to blue cmap = sns.diverging_palette(250, 10, as_cmap=True) # Draw correlation plot with or without duplicates if dropDuplicates: sns.heatmap(df, mask=mask, cmap=cmap, square=True, linewidth=.5, cbar_kws={"shrink": .5}, ax=ax) else: sns.heatmap(df, cmap=cmap, square=True, linewidth=.5, cbar_kws={"shrink": .5}, ax=ax) # Correlation DF of all classes corr = final_df.corr().iloc[[-1],:-1] # Plotting the Correlation DF as a heatmap plt.figure(figsize=(14,1)) sns.heatmap(corr, annot=False, linewidths=.1, cmap="coolwarm") plt.xticks() plt.yticks(rotation=0) plt.show()
这段代码会为我们显示相关性矩阵图
下图显示了相关性的矩阵
我们可以看到,某些指标对确定分类有很大影响。有些指标与决策股票是否值得购买,出售或持有几乎没有关联。现在,我们知道季度报表中的某些指标对于确定分类并不重要,我们可以从数据集中把这些变量进行删除。
特征工程与特征选择
现在,我们已经对数据进行了一些初步探索,我们可以继续进行更深入的研究,或者开始特征工程过程,或更具体地说,进入特征选择阶段。特征工程是对数据进行“再创作”的过程,以增强我们的机器学习模型的过程。有许多用于设计数据集特征变量的方法,它们包括但不限于:
● 创建交互式的特征变量。使两个不同的特征变量相互作用以创建一个全新的特征,比如A特征和B特征的比率或差值。
● 减少特征变量的数量。由于我们有30多个基本特征,因此可以消除一些不重要的特征,以提高模型的整体表现。
● 使用相关领域知识。如果根据经济和金融研究知道哪些特征对股票价格最重要,则可以提高这些特征的优先级。
特征选择
对于我们这个项目,我们希望删除一些不重要的特征变量。这样,我们可以潜在地提高模型的准确性,并减少机器学习的训练时间。这个步骤被称为特征选择;选择模型中必要特征的过程。我们将展示两种不同的特征选择方式。这样一来,我们可以对比两种方法的模型结果。
方法1:根据相关性选择前10个特征
# Correlation DF of all classes corr = final_df.corr().iloc[[-1],:-1] # Sorting our Correlation DF by their absolute values and selecting the top 10 top10_corr = corr.transpose().apply(abs).sort_values(by='Decision', ascending=False)[:10] # Creating a new DF with the features from the top10_corr and joing the 'Decision' class labels top10_corr_df = final_df[top10_corr.index].join(final_df.Decision) # Pickling the DF for use in our Classification models with open("top10_corr_df.pkl", "wb") as fp: pickle.dump(top10_corr_df, fp)
我们排名前10位的和决定股票买入、卖出或持有最相关的特征(从相关程度最高到最低)
使用我们在探索数据集时创建的相关矩阵,我们选择了与决定股票买入、卖出或持有三个类别相关程度最高的前10个特征(请参见上图)。这是通过以下方式完成的:
取每个特征的绝对值(以处理负相关)。
按绝对值排序。
仅选择相关程度最高的前10个特征。
连接类别标签,以便将它们包含在新数据框架中。
将前10个相关数据框架导出为pickle文件。
好的, 现在我们为分类模型提供了一个新的精简的数据集。希望这个新的数据集可以增强我们的分类模型并加快机器学习模型的训练时间。
方法2:根据树分类器选择前10个特征
接下来的“特征选择”方法将比我们刚才做的要复杂一些。通过使用Sci-Kit Learn的library,我们将实现基于决策树的分类器模型,以确定哪些特征最为重要。通过使用此分类器,我们可以确定对股票进行分类时最重要的特征。
# Importing the necessary libraries from sklearn.ensemble import ExtraTreesClassifier # Instatiating the classifier forest = ExtraTreesClassifier(n_estimators=200) # Setting the corresponding variables for our classifier X = final_df.drop(['Decision'], 1) y = final_df.Decision # Fitting the classifier forest.fit(X, y) # Determining the important features importances = forest.feature_importances_ # The standard deviation among the trees for the important features std = np.std([i.feature_importances_ for i in forest.estimators_], axis=0) # Indexing and sorting the important features indices = np.argsort(importances)[::-1] # Assigning the top 10 features as a new DF top10_df = final_df[X.columns[indices][:10]].join(final_df.Decision) # Exporting the top 10 features DF with open("top10_df.pkl", "wb") as fp: pickle.dump(top10_df, fp)
查找特征重要性
接下来,在整理好所有重要特征后,我们将其可视化以准确确定哪些特征被确定为最重要,以了解哪些特征被选择了。
# Matplotlib style to use plt.style.use('seaborn') # Printing out the different features as a list print("Feature Rankings:") # Showing the top 10 features for i in range(10): print(f". : ") # Plotting the top 10 features plt.figure(figsize=(14,7)) plt.title("Feature Importances for the Original Dataset") plt.bar(range(X.shape[1]), importances[indices], yerr=std[indices], align='center') plt.xticks(range(X.shape[1]), X.columns[indices], rotation=90) plt.xlim([-1, 11.5]) plt.show()
可视化我们的特征
运行代码得到以下结果:
根据我们的forest.feature_importances_方法,以下是十大最重要的特征:
1. P/B率
2. 资产
3. 调整后股份分割
4. 股份
5. P/E率
6. 资产周转率
7. 负债
8. 当前资产
9. 期末现金
10. 收入
我们代码的最后一行导出了数据框架的10个最重要功能。现在,我们有两个排名前10的重要特征的数据集。
如果一个特征变量通过两种方法认证都排在前十位,那它就是决定股票该不该买的关键指标啦!
如果你想学习如何用数据科学的方法精准有效地进行预测,那么你就应该系统学习机器学习与统计建模。在营销分析领域,如何有效分配营销预算、科学衡量每一个营销渠道的经济效果、预测营销带来的销量,离不开行业内最推崇的方法——营销组合建模(Marketing Mix Modeling)。MarTechApe携手全球最大广告集团WPP的数据总监、营销分析经理联手推出,业内标准流程的《营销组合建模企业级训练营》第10期,专注于培养营销数据科学家!
从我们的项目中,毕业了将近200名学生,斩获各大公司数据岗位offer:
今天,《营销组合建模企业级训练营》正式开启第10期的招募!
1.营销组合模型训练营是什么?
营销组合模型训练营(Marketing Mix Modeling Bootcamp)是MarTechApe的宝藏项目,由全球最大广告集团 WPP美国办公室的数据总监以及营销分析经理共同授课。在训练营中,你将学习在真实商业情境中如何用营销组合模型解决广告营销最核心的问题——科学合理地评估不同广告对品牌和销售的影响,以统计模型的结果来科学优化广告预算。
训练营的学员收获了:
真正意义上的“用数据和模型解决营销中最重要的问题”的经历。
熟练掌握SQL、R、Tableau等时下最流行的数据处理语言,并用这些技能解决实际问题。
大大提高Media/Advertising Industry的商业意识,熟悉不同媒介渠道的广告活动对不同商业指标的不同回报率(ROI)与有效性(Effectiveness),学会用“营销效果”的视角看待营销活动,理解各大公司市场营销部门、消费者洞察部门的痛点。
跳出学校作业的框架,上手真正商业情境中、实际工作中的实战案例。让校园与实际工作无缝衔接。将学到的Analytics思维方式泛化到其他应用场景,面对Case Study建立系统性解决思路。
提升项目演示Presentation技能,学会如何从原始数据中挖掘具有意义的故事。为客户解决实际问题,提高Business KPI。
完成项目后,辅导老师将帮助你利用这一个惊艳的项目背景打造最引人注目的简历;所有学员获得内推机会,优秀学员获得一对一面试辅导。
2.学员对训练营评价如何?
Marketing Mix Modeling Bootcamp开办至今,收获了大量好评,学员们都觉得Bootcamp的质量非常高,在节课后给我们发来了很多让我们非常感动的评论:
3.训练营老师是谁?
1. 全球最大广告传媒集团WPP | 数据总监
商业分析高级专家
拥有7年数据分析经历
各类SQL、Tableau疑难杂症的go-to person
2. 全球最大广告代理公司GroupM | 营销分析经理
营销效果分析专家。为十多个每年广告预算上亿美元的大客户提供营销效果评估、销售预测等解决方案
拥有6年Marketing Mix Modeling等高阶分析经验,具有丰富的训练新人和带领团队的经验
毕业于Columbia University统计学系
今天,我们非常骄傲地宣布
Marketing Mix Modeling Bootcamp第十期
正式开始报名!
接下来我们就看看训练营的具体课程内容吧!
4.在Bootcamp中可以学到哪些内容?
整个bootcamp分为广告数据源概况、数据处理与可视化、统计建模、深度诊断,共计24小时课时,在两个月内完成。
周末Online Live授课,课后完成老师布置的作业,助教团队在班级群随时答疑,直播录像永久回放。
课程内容涵盖了数据分析岗位的完整工作流程(analytics cycle):
数据收集 Data Acquisition
数据处理和清洗 Data Processing
数据可视化与商业洞察 Data Visualization & Data Story-telling
统计建模 Modeling
模型优化 Optimization
销售预测 Simulation
深度诊断 Side Diagnostics
结果展示 Presentation
每位学员将有一套亲自做的Data成果作品和一套Model成果作品,以及一段完整的为客户解决实际问题的经历。
结课后,每位学员获得提升简历的Project Experience完美描述,所有学员获得内推机会!优秀学员获得额外一对一面试辅导。
报名的学员可在开课前一周获得详细的Syllabus。
学员在前四周会聚焦在数据处理和商业洞察上。学员会面对大量的营销活动数据(如Display、Search、Social、Video、TV等广告数据),根据Media Data的数据源与结构来处理纷繁复杂的数据。并用可视化来呈现出数据洞察。你将学会如何搭建一个数据库、如何利用SQL去处理未经处理的、大型原始数据集,并利用Tableau对数据进行可视化分析。你还将完成对一份数据的商业分析。简而言之,我们将以Data Processing >> Data Visualization >> Insights Generation这样一套体系,系统加强你的数据分析能力以及商业意识。
在真实的世界里,模型用来回答各类不同的商业问题,帮助决策者作出最优的决策。在本次bootcamp的第四~第八周中,你将建立一个真正的Marketing Mix Model!掌握模型最核心的秘诀,调整各类模型参数、学会解读模型结果、优化营销预算、精准预测销售走势。在这个过程中,学会将商业问题翻译成模型问题,用不同的分析手段来回答不同的营销问题,真正做到数据驱动战略决策。
在向你的观众解释Marketing Mix Modeling的模型结果时,Side Diagnostics(深度诊断)往往是一个让你的受众通过商业意义来理解模型结果的重要手段。模型的解释力以及与商业可行性的融合性是决定你的受众是否“买账”的关键因素。因此,Marketing Mix Modeling专门加入深度诊断部分,教你如何用统计的方法说服你的受众!
5.上完Bootcamp,有哪些成果可以展示?
从变量可视化分析、模型解读、营销渠道分析,到战略洞察、PPT演示,学员的精致作业就是他们最好的训练营成果,这一份拿的出手的高品质项目,无论是LinkedIn还是面试展示,都会是脱颖而出的最佳帮手!
学员作品
正是这些实打实的项目经验和能够直接拿到面试官面前展示的作品,让我们的学员在面试的时候信心倍增,让面试官刮目相看!
说了这么多,到底怎么报名这门干货十足物超所值的项目课程呢?
6.报名方式
长按二维码,添加小助手为好友,回复“MMM”,即可报名bootcamp:
小助手(微信ID:yvonne91_wsn)
价格规则
熟悉我们的老用户,应该知道我们一直都是实行阶梯价格的,这次也不例外:
先到先得、越早报名越优惠(原价$1999美元)。以下价格单位为美元:
第1名~第5名:1299美元
第6名~第10名:1499美元
第11名~第15名:1599美元
第16名~第18名:1799美元
第19名~第20名:1999美元(原价)
2020年的你,是否能在更好的公司做更优秀的自己?投资自己,全方位提升能力,为自己增添被验证有效的宝藏项目经历!赶快报名吧!