起因
前一段時間投了一家金融公司的Python開發工程師,讓我做以下事情:
- 以月爲窗口,挑選一隻基金or股票,查看它近2年最大回撤率;
- 找到從08年-至今的金融危機時間段,並呈現在這些危機時間段內,該基金or股票的歷次回撤率。
給了3天時間,代碼我1天不到就寫完了,寫完之後我就去做自己的項目了,沉迷技術無法自拔~~~
3天過後,沒想到打電話過來的是產品經理,完全不問代碼的事情,問我平時是怎麼學習的;問我有沒有考慮爲什麼要分析這些東西;問我以後的方向;問我學習中遇到過的最大的問題是什麼,我說了我最近做的一個網站(http://47.56.205.156/)遇到的問題;
我覺得自己答的都還不錯,也許是沒答到人家內心裏去吧,問了幾個問題之後,我感覺人家貌似情緒有點不對了,然後技術面也沒有,就沒有後續通知了~
言歸正傳,我選了一家老牌的基金 github 源碼和數據
大成滬深300指數A 519300 最大回撤率分析
數據來源:http://fund.eastmoney.com/519300.html?spm=search
天天基金官網:大成滬深300指數A 519300
基金走勢圖 2007 - 2020
官網上分析數據接口,清洗數據之後,我繪製出來的圖 2006 - 2020
1. 以月爲窗口,挑選一隻基金or股票,查看它近2年最大回撤率;
2.找到從08年-至今的金融危機時間段,並呈現在這些危機時間段內,該基金or股票的歷次回撤率。
很多基金成立年限都不高,沒有經歷過金融危機,這隻基金是我找了些資料才找出來的,成立了14個年頭。
github 源碼和數據
代碼-100行
'''
數據來源:http://fund.eastmoney.com/519300.html?spm=search
天天基金官網:大成滬深300指數A 519300
'''
import matplotlib.pyplot as plt
import pandas as pd
import datetime
import pylab as pl
# 讀取數據
df = pd.read_csv('大成滬深300指數A-519300.txt', sep='\t', header=None, names=['x', 'y', 'equityReturn'])
df.index = pd.to_datetime(df.x) # 使用x時間列爲索引列,定位快
df = df.drop(['x'], axis=1) # 刪除x列
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.plot(df.index, df.y) # 根據數據繪製原走勢圖
plt.title('大成滬深300指數A-519300走勢圖')
plt.show()
'''
計算每個月的最大回撤率
'''
res = []
# 先按年分組,再按月分組
for indexs, groupby_year_month in df.groupby([df.index.year, df.index.month]):
_ = list(groupby_year_month['y'].values) # 各個月份的y值列表
# 尋找最大回撤率
_min = 1 # 最低點索引
_max = 0 # 最高點索引
for i, y in enumerate(_):
if y < _[_min]:
_min = i
if y > _[_max]:
_max = i
# 如果最低點的索引大於最高點的索引,找到最大撤回率
if _min > _max:
pass
# 否則,重新尋找最低點前的最高點
else:
_max = 0
for i in range(_min):
if (_[i] > _[_max]):
_max = i
t = [groupby_year_month.index[0], _[_max], _[_min], _[_max] - _[_min], (_[_max] - _[_min]) / _[_max] * 100]
res.append(t)
# 轉DataFrame
result = pd.DataFrame(res, columns=["date", "max", "min", "diff", "rate"])
# 只保留年月
result['date'] = result['date'].apply(lambda x : datetime.datetime.strftime(x, "%Y-%m"))
# 日期列轉爲索引
result.index = pd.to_datetime(result['date'])
# 刪除日期列
result = result.drop(['date'], axis=1)
'''
1、以月爲窗口,挑選一隻基金or股票,查看它近2年最大回撤率;
'''
# 取近兩年
today = datetime.date.today()
two_year_ago = datetime.datetime(today.year - 2, today.month - 1, today.day)
near_two_year_df = result[(result.index >= two_year_ago)]
# 以月爲窗口的最大回撤率
print(f'以月爲窗口,近2年最大回撤率: {round(near_two_year_df["rate"].max(), 4)}%')
# 以月爲窗口的回撤率繪圖
plt.plot(near_two_year_df.index, near_two_year_df['rate'])
plt.title('大成滬深300指數A-519300 近兩年的月回撤率')
plt.show()
'''
2、找到從08年-至今的金融危機時間段,並呈現在這些危機時間段內,該基金or股票的歷次回撤率。;
'''
crisis_start = datetime.datetime(2007, 1, 1) # 金融危機開始
crisis_end = datetime.datetime(2009, 8, 1) # 結束
crisis_df = df[(df.index >= crisis_start) & (df.index <= crisis_end)]
_ = list(crisis_df['y'].values) # 各個月份的y值列表
# 尋找最大回撤率
_min = 1 # 最低點索引
_max = 0 # 最高點索引
for i, y in enumerate(_):
if y < _[_min]:
_min = i
if y > _[_max]:
_max = i
# 如果最低點的索引大於最高點的索引,找到最大撤回率
if _min > _max:
pass
# print(True)
# 否則,重新尋找最低點前的最高點
else:
_max = 0
for i in range(_min):
if(_[i] > _[_max]):
_max = i
rate = round((_[_max] - _[_min]) / _[_max] * 100, 4)
print('\n08金融危機時間段:\n最高點淨值:', _[_max], '\t最低點淨值:', _[_min], '\t回撤', (_[_max] - _[_min]))
print(f'最大回撤率: {rate}%')
'''
繪圖
'''
min = crisis_df[crisis_df.y == _[_min]]
max = crisis_df[crisis_df.y == _[_max]]
min_date = datetime.datetime.strftime(list(min.index)[0], '%Y-%m-%d')
max_date = datetime.datetime.strftime(list(max.index)[0], '%Y-%m-%d')
min_y = list(min.y)[0]
max_y = list(max.y)[0]
show_min = '['+str(min_date)+' '+ str(min_y)+']'
show_max = '['+str(max_date)+' '+ str(max_y)+']'
plt.plot(crisis_df.index, crisis_df.y) # 繪製折線圖
plt.annotate(show_min, xytext=(min_date, min_y), xy=(min_date, min_y)) # 標記提示
plt.annotate(show_max, xytext=(max_date, max_y), xy=(max_date, max_y)) # 標記提示
plt.scatter(min_date, min_y, color='r') # 標記最低點
plt.scatter(max_date, max_y, color='r') # 標記最高點
plt.plot([])
plt.plot([min.index, max.index],[min_y, max_y], color='b', linestyle='--') # 連接最低淨值點和最高淨值點
tips = crisis_df[crisis_df.index == '2008-03-03']
plt.annotate(f' {rate}%', xytext=(tips.index, tips.y), xy=(tips.index, tips.y)) # 標記提示
plt.title('2008年金融危機最大回撤率')
pl.xticks(rotation=60)
plt.show()