<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          基金定投如何選擇買賣點?——關(guān)于定投的擇時研究

          共 10688字,需瀏覽 22分鐘

           ·

          2021-03-25 14:16


          ↑↑↑關(guān)注后"星標"簡說Python
          人人都可以簡單入門Python、爬蟲、數(shù)據(jù)分析
           簡說Python推薦 
          來源|Python讀財
          作者|易執(zhí)


          大家好,我是老表~

          基金定投是近幾年各種理財平臺比較推崇的一種理財方式,大多數(shù)關(guān)于定投的宣傳語中,會有這”六字箴言“:不擇時,長期投。

          所謂擇時,便是選擇合適的買點和賣點,那基金定投真的用不著擇時么?本文就用數(shù)據(jù)來探究一下是否需要擇時以及該如何進行擇時。

          是否需要擇時?

          下面上的這張圖是2004年到2020年16年間,上證指數(shù)和道瓊斯指數(shù)的走勢對比圖,大致代表了兩個不同資本市場的行情走勢。

          從圖中可以看出兩大指數(shù)的走勢都頗具特點,道指基本是一種長牛的走勢,對于這種走勢,如果進行指數(shù)基金定投是可以不擇時的。

          而對上證指數(shù)而言,走勢呈現(xiàn)一種比較明顯的周期性,牛短熊長,一個牛熊周期大概為7.5年,整體的重心是向上移動的。如果進行長期投資但不進行擇時,雖然長周期來看也可以獲得正向的收益,但卻享受不了牛市帶來的情緒溢價,就像坐了趟過山車,圖個刺激。

          所以,對基金定投而言,還是有必要進行擇時操作的,在指數(shù)低估時買入,等牛市來時賣出,那么該如何進行擇時呢?

          擇時的基本策略

          定投中可以根據(jù)股指的點位或估值高低等指標進行擇時操作,本文主要研究基于估值的擇時操作,在估值較低時開始定投,待估值達到歷史較高水平時賣出,因此如何定義估值是高還是低便是擇時操作的關(guān)鍵。

          由于滬深300指數(shù)能夠較好地反映滬深兩市的走勢,常被設(shè)為基金業(yè)績的比較基準。所以本文其為例進行研究,并以市盈率(PE)為估值指標,探究不同估值區(qū)間的擇時效果。

          具體策略:擇時的指標為該指數(shù)當前的PE估值在過去7年(兼顧一輪牛熊周期)的分位數(shù)水平,若分位數(shù)水平低于定義的區(qū)間下限,開啟定投周期,直到估值的分位數(shù)水平高于區(qū)間上限,將持有的份額全部賣出。賣出后,要等到估值水平再次低于區(qū)間下限,開始下一輪定投,按照這個規(guī)則持續(xù)運行。

          回測的具體參數(shù)如下:

          投資標的:易方達滬深 300ETF聯(lián)接A(110020.OF)

          回測時間范圍:2013年1月1日-2020年1月1日

          估值指標:市盈率(PE)

          申購費率:0.15%

          贖回費率:0.5%

          估值區(qū)間:20%-80,30%-80%,40%-80%,20%-70%,30%-70%,40%-70%

          每次定投金額:5000

          頻率:每周一

          回測結(jié)果

          具體的回測框架已經(jīng)被我封裝成可以直接調(diào)用的函數(shù)run_strategy,代碼部分較長,已貼到文末,大家可以直接復制使用。下面直接以圖形化的方式展示回測結(jié)果。

          注: 結(jié)果圖中,用基金凈值走勢近似指數(shù)走勢,黃色陰影代表定投輪此區(qū)間,藍色陰影代表當前估值水平在過去7年的百分位數(shù)(右軸表示)。

          不擇時,一直定投

          如不進行擇時,則在這七年間每周一均進行買入,一共定投了334期,總收益率為37.71%,年化的收益率大概為4.7%,總體結(jié)果算不上理想。

          20%-80%區(qū)間

          設(shè)定低估區(qū)間為20%以下,高估區(qū)間為80%以上則完美的吃到了2014-2015年的這輪牛市,在指數(shù)達到頂點前于左側(cè)賣出。期間共進行了113次定投,該輪定投的收益率達到了92.8%,但由于后續(xù)估值百分位再也沒有達到20%以下,之后沒有產(chǎn)生任何買賣行為。

          30%-80%區(qū)間

          將低估區(qū)間的范圍擴大到30%后,定投輪次加多了一輪,幾乎在2018年末最低點抄底,趕上了2019年初的小陽春行情,第二階段的定投了52期,整體收益率為10.2%。

          40%-80%區(qū)間

          將低估區(qū)間進一步放寬到40%后,2013-2020年這七年間共進行了3輪定投,三次定投的期數(shù)分別為113次,88次,以及68次,三個輪次定投所產(chǎn)生的收益也較為可觀,雖然在16年和18年四季度定投產(chǎn)生了較大回撤,但也把握住了后期的行情。

          下面將高估區(qū)間降低到70%,看進一步的回測情況。

          20%、30%、40%-70%區(qū)間

          下面一起顯示定投區(qū)間分別為20%-70%,30%-70%以及40%-70%區(qū)間的回測結(jié)果圖

          若將估值70%分位數(shù)以上標定為高估區(qū),則相較80%更早的逃頂賣出,在牛市行情中更早落袋為安,也損失了部分潛在收益。與此同時,以70%分位數(shù)為賣出點會使得賣出頻率相應地也增加了。尤其是40%-70%區(qū)間,此時的高估和低估區(qū)距離較為接近,買入和賣出更加頻繁。

          匯總結(jié)果

          將以上所有回測結(jié)果進行整理,得到下面的統(tǒng)計表

          表中

          絕對收益比 = 各區(qū)間回測總收益/不擇時總收益

          年化收益率 = 期間絕對收益/(首輪定投總期數(shù)*每期定投額)

          由于定投是采用增量資金進行投資,如果期間定投了多輪,其實總收益率比較難去定義,所以這里選用絕對收益和我自己定義的年化收益綜合去衡量(不一定科學)

          如果從絕對收益的結(jié)果來看,不擇時的絕對收益是最高的,但其總共定投了334期。40%-80%估值區(qū)間的回測結(jié)果用269期定投取得了和334期定投差不多的絕對收益值,且年化收益上更是遠遠跑贏。如果單從本次回測結(jié)果來看,綜合考慮資金利用效率等因素,采用40%-80%區(qū)間進行擇時的效果最好。

          但實際進行選擇時應該結(jié)合自己的風險偏好,低估區(qū)間設(shè)置得越高,一方面能收集更多籌碼,但同時也意味著可能會承擔更大的回撤風險。高估區(qū)間設(shè)置得越低,雖然會錯過潛在的收益,但也能提早落地為安。

          代碼

          具體的代碼我已封裝好,有興趣的可以自己進行其他指數(shù)的研究。根據(jù)目前Tushare支持的數(shù)據(jù),下面回測框架可以研究滬深300指數(shù)、創(chuàng)業(yè)板指數(shù)、中證500指數(shù)、上證50指數(shù)等主流的寬基指數(shù)的定投策略。

          import pandas as pd
          import numpy as np
          import matplotlib.pyplot as plt
          import tushare as ts
          import warnings
          from IPython.display import display
          from tqdm import tqdm_notebook
          from datetime import *
          warnings.filterwarnings("ignore")
          %matplotlib inline

          pro = ts.pro_api()
          plt.rcParams["font.sans-serif"] = ["FangSong"]

          def run_strategy(index_code="",fund_code="",money_per_time=5000,
          start_date=None,end_date=None,v_low = None,
          v_high = None,plot=True)
          :


          fund_df = pro.fund_nav(ts_code = fund_code)
          fund_df = fund_df.loc[fund_df.update_flag=='0',['ts_code','end_date','unit_nav']].rename(columns = {'end_date':'trade_date'})
          fund_df = fund_df[(fund_df.trade_date>=start_date) & (fund_df.trade_date<=end_date)]
          fund_df["trade_date"] = pd.to_datetime(fund_df.trade_date)
          fund_df.sort_values(by="trade_date",inplace=True)
          fund_df.reset_index(drop=True,inplace=True)

          # tushare提取數(shù)據(jù)有限制
          # 分開提取然后合并數(shù)據(jù)
          index_start_date = str(int(start_date[:4])-7) + start_date[4:]
          index_end_date = end_date
          index_valuation_1 = pro.index_dailybasic(ts_code = "000300.SH",start_date = index_start_date,end_date = start_date,fields="trade_date,pe_ttm")
          index_valuation_2 = pro.index_dailybasic(ts_code = "000300.SH",start_date = start_date,end_date = index_end_date,fields="trade_date,pe_ttm")
          index_valuation = pd.concat([index_valuation_1,index_valuation_2],axis=0)
          index_valuation["trade_date"] = pd.to_datetime(index_valuation.trade_date)
          index_valuation.sort_values(by="trade_date",inplace=True)
          index_valuation.set_index("trade_date",inplace=True)



          # 回測時需要計算的指標
          fund_df["units"] = np.nan
          fund_df["total_units"] = np.nan
          fund_df["market_value"] = np.nan
          fund_df["signal"] = np.nan
          fund_df["avg_unit_cost"] = np.nan
          fund_df["return_rate"] = np.nan
          fund_df["round"] = np.nan
          fund_df["percentile"] = np.nan
          round_num = 0
          round_on = False

          # money_per_time = 5000

          # 循環(huán)進行回測
          # 申購費率設(shè)置為0.15%
          # 贖回費率設(shè)置為0.5%
          for i in tqdm_notebook(range(len(fund_df))):
          valuation_start_date = (fund_df.loc[i,"trade_date"]-pd.Timedelta(7,unit="y")).date()
          valuation_end_date = fund_df.loc[i,"trade_date"]
          valuation_data = index_valuation.loc[valuation_start_date:valuation_end_date].iloc[:,0].values.tolist()

          valuation_high = np.percentile(valuation_data,v_high)
          valuation_low = np.percentile(valuation_data,v_low)
          now = valuation_data[-1]

          fund_df.loc[i,"percentile"] = np.round((sorted(valuation_data).index(now)+1)/len(valuation_data),4)
          weekday = valuation_end_date.dayofweek



          if now<=valuation_low and round_on == False:
          round_on = True
          round_num += 1

          if round_on:
          if now < valuation_high:
          if weekday==0:
          fund_df.loc[i,"round"] = round_num
          fund_df.loc[i,"signal"] = 1
          fund_df.loc[i,"units"] =np.round((money_per_time - money_per_time * 0.0015)/fund_df.loc[i,"unit_nav"],2)
          fund_df.loc[i,"total_units"] = fund_df.loc[(fund_df.signal==1).values & (fund_df["round"]==round_num).values,"units"].sum()
          fund_df.loc[i,"market_value"] = fund_df.loc[i,"total_units"] * fund_df.loc[i,"unit_nav"]
          fund_df.loc[i,"avg_unit_cost"] = (len(fund_df[(fund_df.signal==1).values & (fund_df["round"]==round_num).values])*money_per_time)/fund_df.loc[i,"total_units"]
          fund_df.loc[i,"return_rate"] = np.round(fund_df.loc[i,"unit_nav"]/fund_df.loc[i,"avg_unit_cost"] -1,4)

          else:

          fund_df.loc[i,"signal"] = 0
          fund_df.loc[i,"units"] = -1 * fund_df.loc[fund_df.signal==1,"total_units"].iloc[-1]
          fund_df.loc[i,"total_units"] = 0
          fund_df.loc[i,"market_value"] = 0
          fund_df.loc[i,"avg_unit_cost"] = 0
          fund_df.loc[i,"return_rate"] = np.round((fund_df.loc[i,"unit_nav"]*0.995)/fund_df.loc[fund_df.signal==1,"avg_unit_cost"].iloc[-1] -1,4)
          fund_df.loc[i,"round"] = round_num

          round_on = False


          # 結(jié)果指標的計算
          action_rounds = fund_df['round'].value_counts().index
          result_list = []
          for action_round in action_rounds:
          round_df = fund_df.loc[fund_df["round"]==action_round].reset_index(drop=True)
          is_sell = True if round_df.loc[len(round_df)-1,'signal']== 0 else False
          #判斷該定投輪次是否已賣出
          if is_sell:
          start_date = round_df.loc[0,'trade_date']
          n_period = len(round_df) - 1
          end_date = round_df.loc[n_period,'trade_date']
          avg_unit_cost = round_df.loc[n_period-1,"avg_unit_cost"]
          final_unit_nav = round_df.loc[n_period,"unit_nav"]
          return_rate = round_df.loc[n_period,"return_rate"]
          else:
          start_date = round_df.loc[0,'trade_date']
          n_period = len(round_df)
          end_date = round_df.loc[n_period-1,'trade_date']
          avg_unit_cost = round_df.loc[n_period-1,"avg_unit_cost"]
          final_unit_nav = round_df.loc[n_period-1,"unit_nav"]
          return_rate = round_df.loc[n_period-1,"return_rate"]
          result_list.append([start_date,end_date,n_period,avg_unit_cost,final_unit_nav,return_rate])

          result_df = pd.DataFrame(result_list,columns=['起始日','截止日','投資期數(shù)','單位平均成本','期末單位凈值','總收益率'])
          display(result_df)
          y_rate = ((result_df["投資期數(shù)"]*result_df["總收益率"]).sum()/result_df["投資期數(shù)"].sum()+1)**(1/7)-1
          income = (np.sum(result_df["投資期數(shù)"]*result_df["總收益率"])*5000)
          print("年化收益率:{:.2f}%".format(y_rate*100))
          print("絕對收益:{}".format(income))

          if plot:
          fig,ax1 = plt.subplots(figsize=(12,8))
          fig.text(x=0.1, y=0.92, s=' {low}%-{high}%區(qū)間定投結(jié)果 '.format(low=v_low,high=v_high), fontsize=32,
          weight='bold', color='white', backgroundcolor='#3c7f99')
          hq_plot = fund_df[["trade_date","unit_nav"]]
          x1 = hq_plot["trade_date"].values
          y1 = hq_plot["unit_nav"].values
          buy_signal = fund_df.loc[fund_df.signal==1,["trade_date","unit_nav"]]
          x2 = buy_signal["trade_date"].values
          y2 = buy_signal["unit_nav"].values
          sell_signal = fund_df.loc[fund_df.signal==0,["trade_date","unit_nav"]]
          x3 = sell_signal["trade_date"].values
          y3 = sell_signal["unit_nav"].values

          # 繪制基金凈值走勢
          # 繪制買點和賣點
          ax1.plot(x1,y1,linewidth=1.5,label='指數(shù)走勢')
          ax1.scatter(x2,y2,marker="^",c = "r",label = "買點")
          ax1.scatter(x3,y3,marker="v",c="g",label = "賣點")
          ax1.spines['top'].set_visible(False)
          ax1.spines['bottom'].set_visible(False)
          ax1.set_ylabel("基金凈值",fontdict={"size":16})
          ax1.tick_params(axis='x',length=0,labelsize=16)
          ax1.tick_params(axis='y',labelsize=16)
          ax1.margins(0.01,0.02)
          ax1.legend(fontsize=14)

          # 繪制每日的估值百分位數(shù),并用藍色陰影部分表示
          ax2 = ax1.twinx()
          ax2.plot(x1,fund_df["percentile"].values,color="#87cefa",alpha=0.1,label="近七年P(guān)E")
          ax2.fill_between(x1,0,fund_df["percentile"].values,color = "#87cefa",alpha=0.2)
          ax2.spines['top'].set_visible(False)
          ax2.spines['bottom'].set_visible(False)
          ax2.set_ylabel("估值百分位數(shù)",fontdict={"size":16,'rotation':270},labelpad=20)
          ax2.tick_params(axis='x',length=0,labelsize=16)
          ax2.tick_params(axis='y',labelsize=16)
          ax2.set_yticklabels(['' ,'0%','20%','40%','60%','80%'])
          ax2.margins(0.01,0.02)

          # 用黃色陰影表示定投輪次
          for i in range(len(result_df)):
          round_start = result_df.loc[i,'起始日']
          round_end = result_df.loc[i,'截止日']
          date_span = pd.date_range(round_start, round_end)

          ax1.fill_between(date_span,np.min(y1),np.max(y1),facecolor="#ffff4d",alpha=0.2)

          plt.show()


          注:本文根據(jù)數(shù)據(jù)研究所得,不構(gòu)成任何投資意見!


          -END-


          文末推薦一本《Python數(shù)據(jù)分析從入門到精通》,本書循序漸進地講解了使用Python語言實現(xiàn)數(shù)據(jù)分析的核心知識,并通過具體實例的實現(xiàn)過程演示了數(shù)據(jù)分析的方法和流程,共12章,內(nèi)容包括Python語言基礎(chǔ)、處理網(wǎng)絡(luò)數(shù)據(jù)、網(wǎng)絡(luò)爬蟲實戰(zhàn)、處理特殊文本格式、使用數(shù)據(jù)庫保存數(shù)據(jù)、操作處理CSV文件、操作處理JSON數(shù)據(jù)、使用庫matplotlib實現(xiàn)數(shù)據(jù)可視化處理、使用庫pygal實現(xiàn)數(shù)據(jù)可視化處理、使用庫numPy實現(xiàn)數(shù)據(jù)可視化處理、使用庫pandas實現(xiàn)數(shù)據(jù)可視化處理和大數(shù)據(jù)實戰(zhàn)案例。Python數(shù)據(jù)分析從入門到精通簡潔而不失技術(shù)深度,內(nèi)容豐富全面。


          【更多福利】

          掃下方二維碼添加我的私人微信,可以在我的朋友圈獲取最新的Python學習資料,以及近期推文中的源碼或者其他資源,另外不定期開放學習交流群,以及朋友圈福利(送書、紅包、學習資源等)。

          掃碼查看我朋友圈

          獲取最新學習資源

          學習更多:
          整理了我開始分享學習筆記到現(xiàn)在超過250篇優(yōu)質(zhì)文章,涵蓋數(shù)據(jù)分析、爬蟲、機器學習等方面,別再說不知道該從哪開始,實戰(zhàn)哪里找了

          點贊”傳統(tǒng)美德不能丟 

          瀏覽 84
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  中文字幕东京热 | 日韩人妻丰满无码区A片 | 国产熟女热 | 欧美午夜一区 | 中国精品毛片 |