【Python】基金/股票 最大回撤率計算與繪圖(附源碼和數據)

起因

前一段時間投了一家金融公司的Python開發工程師,讓我做以下事情:

  1. 以月爲窗口,挑選一隻基金or股票,查看它近2年最大回撤率;
  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()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章