<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>

          量化投資的強(qiáng)化學(xué)習(xí)神器!FinRL 入門(mén)指南

          共 9868字,需瀏覽 20分鐘

           ·

          2022-07-06 08:22


          本文將基于FinRL教你實(shí)現(xiàn)一個(gè)超額收益7%的強(qiáng)化學(xué)習(xí)模型。關(guān)于強(qiáng)化學(xué)習(xí)的基礎(chǔ)知識(shí),可以閱讀我們以前發(fā)表的一篇基礎(chǔ)文章:

          什么是強(qiáng)化學(xué)習(xí)?預(yù)測(cè)股票的效果如何?

          使用強(qiáng)化學(xué)習(xí)預(yù)測(cè)股價(jià),類(lèi)似于心理學(xué)中的操作性條件反射原理,你需要在決策的時(shí)候采取合適的行動(dòng) (Action) 使獎(jiǎng)勵(lì)最大化。與監(jiān)督學(xué)習(xí)預(yù)測(cè)未來(lái)的數(shù)值不同,強(qiáng)化學(xué)習(xí)根據(jù)輸入的狀態(tài)(如當(dāng)日開(kāi)盤(pán)價(jià)、收盤(pán)價(jià)等),輸出系列動(dòng)作(例如:買(mǎi)進(jìn)、持有、賣(mài)出),并對(duì)好的動(dòng)作結(jié)果不斷進(jìn)行獎(jiǎng)勵(lì),對(duì)差的動(dòng)作結(jié)果不斷進(jìn)行懲罰,使得最后的收益最大化,實(shí)現(xiàn)自動(dòng)交易。

          如果你從頭開(kāi)始編寫(xiě)一套強(qiáng)化學(xué)習(xí)的代碼,時(shí)間成本和試錯(cuò)成本會(huì)比較高。而本文的主角 FinRL 框架,能夠幫助你極大地減少學(xué)習(xí)成本、時(shí)間成本和試錯(cuò)成本。下面就介紹一下 FinRL 的使用方法。

          1.準(zhǔn)備



          開(kāi)始之前,你要確保Python和pip已經(jīng)成功安裝在電腦上,如果沒(méi)有,可以訪問(wèn)這篇文章:超詳細(xì)Python安裝指南 進(jìn)行安裝。

          (可選1) 如果你用Python的目的是數(shù)據(jù)分析,可以直接安裝Anaconda:Python數(shù)據(jù)分析與挖掘好幫手—Anaconda,它內(nèi)置了Python和pip.

          (可選2) 此外,推薦大家用VSCode編輯器,它有許多的優(yōu)點(diǎn):Python 編程的最好搭檔—VSCode 詳細(xì)指南

          請(qǐng)選擇以下任一種方式輸入命令安裝依賴
          1. Windows 環(huán)境 打開(kāi) Cmd (開(kāi)始-運(yùn)行-CMD)。
          2. MacOS 環(huán)境 打開(kāi) Terminal (command+空格輸入Terminal)。
          3. 如果你用的是 VSCode編輯器 或 Pycharm,可以直接使用界面下方的Terminal.

          # 首先克隆項(xiàng)目
          git clone https://github.com/AI4Finance-Foundation/FinRL.git
          # 進(jìn)入剛克隆的項(xiàng)目,安裝依賴
          cd FinRL
          pip install


          請(qǐng)注意 Python 版本要大于等于 3.7。此外,如果你的當(dāng)前Python環(huán)境下安裝了 zipline,請(qǐng) pip uninstall 掉 zipline,因?yàn)閆ipline與FinRL不兼容。

          可能出現(xiàn)的錯(cuò)誤:

          如果你出現(xiàn)以下紅字提示:

          error: command 'swig.exe' failed: No such file or directory


          請(qǐng)使用conda安裝swig:

          conda install swig


          然后重新執(zhí)行 pip install . 即可。

          2.模型訓(xùn)練



          運(yùn)行官方示例的時(shí)候會(huì)使用到雅虎財(cái)經(jīng)的數(shù)據(jù),雅虎財(cái)經(jīng)在中國(guó)已經(jīng)關(guān)閉服務(wù),因此你會(huì)需要VPN才能下載雅虎財(cái)經(jīng)的數(shù)據(jù)。

          cd FinRL
          python Stock_NeurIPS2018.py


          運(yùn)行的時(shí)候大概率會(huì)遇到這個(gè)問(wèn)題(2022-07-03):

          FileNotFoundError: Please set your own ALPACA_API_KEY and ALPACA_API_SECRET in config_private.py


          這是官網(wǎng)的一個(gè)不嚴(yán)謹(jǐn)實(shí)現(xiàn)導(dǎo)致的,你可以將 finrl/main.py 中25~30行的代碼移動(dòng)到第100行,如下所示:

          此外,在運(yùn)行代碼的時(shí)候,你可能會(huì)遇到無(wú)法下載數(shù)據(jù)的問(wèn)題,這是因?yàn)檠呕⒇?cái)經(jīng)在中國(guó)已經(jīng)關(guān)閉服務(wù),你需要在 Stock_NeurIPS2018.py 的第172行代碼 fetch_data 函數(shù)中添加proxy參數(shù):


          # 公眾號(hào):二七阿爾量化
          # 此處我的代理是10809端口,你應(yīng)該按需修改
          df = YahooDownloader(start_date = '2009-01-01',
                               end_date = '2021-10-31',
                               ticker_list = config_tickers.DOW_30_TICKER
                               ).fetch_data(proxy={"http": "http://127.0.0.1:10809", "https": "https://127.0.0.1:10809"})


          此外,在 finrl/finrl_meta/preprocessor/preprocessors.py 的第191行,你也需要增加proxy參數(shù):

          # 公眾號(hào):二七阿爾量化
          # 此處我的代理是10809端口,你應(yīng)該按需修改
          df_vix = YahooDownloader(
                      start_date=df.date.min(), end_date=df.date.max(), ticker_list=["^VIX"]
                  ).fetch_data(proxy={"http": "http://127.0.0.1:10809", "https": "https://127.0.0.1:10809"})



          正常運(yùn)行起來(lái)的模型訓(xùn)練如下圖所示:


          下面是我簡(jiǎn)化版的到SAC模型訓(xùn)練為止的全部代碼:

          上滑查看更多代碼

          # 公眾號(hào):二七阿爾量化
          from finrl import config
          from finrl import config_tickers
          from finrl.main import check_and_make_directories

          import pandas as pd

          from finrl.finrl_meta.preprocessor.yahoodownloader import YahooDownloader
          from finrl.finrl_meta.preprocessor.preprocessors import FeatureEngineer, data_split
          from finrl.finrl_meta.env_stock_trading.env_stocktrading import StockTradingEnv
          from finrl.agents.stablebaselines3.models import DRLAgent

          import sys
          sys.path.append("../FinRL-Library")

          import itertools

          from finrl.config import (
              DATA_SAVE_DIR,
              TRAINED_MODEL_DIR,
              TENSORBOARD_LOG_DIR,
              RESULTS_DIR,
          )

          check_and_make_directories([DATA_SAVE_DIR, TRAINED_MODEL_DIR, TENSORBOARD_LOG_DIR, RESULTS_DIR])


          '''
          # Part 1. 下載數(shù)據(jù)
          '''


          df = YahooDownloader(
              start_date='2009-01-01',
              end_date='2021-10-31',
              ticker_list=config_tickers.DOW_30_TICKER
          ).fetch_data(proxy={"http": "http://127.0.0.1:10809", "https": "https://127.0.0.1:10809"})


          print(f"config_tickers.DOW_30_TICKER: {config_tickers.DOW_30_TICKER}")


          print(f"df.shape: {df.shape}")


          df.sort_values(['date','tic'],ignore_index=True).head()


          '''
          # Part 2: 數(shù)據(jù)預(yù)處理
          '''


          fe = FeatureEngineer(
                              use_technical_indicator=True,
                              tech_indicator_list=config.INDICATORS,
                              use_vix=True,
                              use_turbulence=True,
                              user_defined_feature = False)

          processed = fe.preprocess_data(df)


          list_ticker = processed["tic"].unique().tolist()
          list_date = list(pd.date_range(processed['date'].min(),processed['date'].max()).astype(str))
          combination = list(itertools.product(list_date,list_ticker))

          processed_full = pd.DataFrame(combination,columns=["date","tic"]).merge(processed,on=["date","tic"],how="left")
          processed_full = processed_full[processed_full['date'].isin(processed['date'])]
          processed_full = processed_full.sort_values(['date','tic'])

          processed_full = processed_full.fillna(0)


          processed_full.sort_values(['date','tic'],ignore_index=True).head(10)

          # 訓(xùn)練集
          train = data_split(processed_full, '2009-01-01','2020-07-01')
          # 測(cè)試集
          trade = data_split(processed_full, '2020-07-01','2021-10-31')

          print(f"len(train): {len(train)}")
          print(f"len(trade): {len(trade)}")
          print(f"train.tail(): {train.tail()}")
          print(f"trade.head(): {trade.head()}")
          print(f"config.INDICATORS: {config.INDICATORS}")
          stock_dimension = len(train.tic.unique())
          state_space = 1 + 2*stock_dimension + len(config.INDICATORS)*stock_dimension
          print(f"Stock Dimension: {stock_dimension}, State Space: {state_space}")

          buy_cost_list = sell_cost_list = [0.001] * stock_dimension
          num_stock_shares = [0] * stock_dimension

          env_kwargs = {
              "hmax": 100,
              "initial_amount": 1000000,
              "num_stock_shares": num_stock_shares,
              "buy_cost_pct": buy_cost_list,
              "sell_cost_pct": sell_cost_list,
              "state_space": state_space,
              "stock_dim": stock_dimension,
              "tech_indicator_list": config.INDICATORS,
              "action_space": stock_dimension,
              "reward_scaling": 1e-4
          }


          e_train_gym = StockTradingEnv(df = train, **env_kwargs)

          env_train, _ = e_train_gym.get_sb_env()
          print(f"type(env_train): {type(env_train)}")


          '''
          # Part 3: 模型訓(xùn)練
          '''

          agent = DRLAgent(env = env_train)
          SAC_PARAMS = {
              "batch_size": 128,
              "buffer_size": 1000000,
              "learning_rate": 0.0001,
              "learning_starts": 100,
              "ent_coef": "auto_0.1",
          }

          model_sac = agent.get_model("sac", model_kwargs = SAC_PARAMS)


          trained_sac = agent.train_model(model=model_sac,
                                       tb_log_name='sac',
                                       total_timesteps=60000)

          3.模型測(cè)試



          在這一部分,我們將使用測(cè)試集進(jìn)行模擬交易,檢驗(yàn)?zāi)P偷男Ч?/p>

          在env_kwargs中,我們?cè)O(shè)置了初始資金為1000000美元,測(cè)試也會(huì)以這個(gè)初始資金為起點(diǎn)。

          # 測(cè)試
          e_trade_gym = StockTradingEnv(df=trade, turbulence_threshold=70, risk_indicator_col='vix', **env_kwargs)
          df_account_value, df_actions = DRLAgent.DRL_prediction(
              model=trained_sac,
              environment=e_trade_gym
          )
          print(f"df_account_value.tail(): {df_account_value.tail()}")


          如下:


          此外,df_actions內(nèi)保存了每天的持倉(cāng)記錄:

          print(f"df_actions.head(): {df_actions.head()}")



          調(diào)用 backtest_stats 函數(shù),能獲得完整的回測(cè)結(jié)果:

          print("==============Get Backtest Results===========")
          now = datetime.datetime.now().strftime('%Y%m%d-%Hh%M')

          perf_stats_all = backtest_stats(account_value=df_account_value)
          perf_stats_all = pd.DataFrame(perf_stats_all)
          perf_stats_all.to_csv("./"+config.RESULTS_DIR+"/perf_stats_all_"+now+'.csv')


          結(jié)果如下所示:

          可以見(jiàn)到,模型的年化收益為30%,累計(jì)凈值收益為43%.

          但是這段時(shí)間為美股的牛市,我們還需要以道瓊斯指數(shù)為基準(zhǔn)計(jì)算超額收益,才能更直觀地展示模型的效果:

          print("==============Get Baseline Stats===========")
          baseline_df = get_baseline(
                  ticker="^DJI",
                  start = df_account_value.loc[0,'date'],
                  end = df_account_value.loc[len(df_account_value)-1,'date'])

          stats = backtest_stats(baseline_df, value_col_name = 'close')



          可見(jiàn)模型還是具有超額收益的,我們將其繪制為圖表更清晰地表達(dá):

          backtest_result = backtest_plot(df_account_value, 
                       baseline_ticker = '^DJI',
                       baseline_start = df_account_value.loc[0,'date'],
                       baseline_end = df_account_value.loc[len(df_account_value)-1,'date'])
          with open("backtest_result.html", "w") as file:
              file.write(backtest_result)



          作者給我們內(nèi)置了許多漂亮的回測(cè)圖表,非常好用。但我們只需要看最關(guān)鍵的cumulative returns. 從圖中可以看到這個(gè)模型(綠色的線條)一開(kāi)始的表現(xiàn)并不如指數(shù),但是到了后面,它的表現(xiàn)漸漸優(yōu)于指數(shù)。

          當(dāng)然,這是官方給的示例數(shù)據(jù),大家可以用自己的因子補(bǔ)充數(shù)據(jù),將模型完善地更好。本文的示例中使用的是SAC模型,你也可以嘗試其他的強(qiáng)化學(xué)習(xí)模型。

          總之,F(xiàn)inrl 只能提供你一雙”巨人的肩膀“,你應(yīng)該根據(jù)自己的實(shí)際業(yè)務(wù)場(chǎng)景和數(shù)據(jù)類(lèi)型使用不同的優(yōu)化方法。

          4.其他



          FinRL不只能支持美股,它還支持A股的部分?jǐn)?shù)據(jù)源,如聚寬、米筐和Tushare:

          以downloader為例,用法很簡(jiǎn)單,庫(kù)中提供了 Tushare 的 downloader, 你只需要把:

          from finrl.finrl_meta.preprocessor.yahoodownloader import YahooDownloader


          替換為:

          from finrl.finrl_meta.preprocessor.tusharedownloader import TushareDownloader


          并進(jìn)行相應(yīng)的代碼修改即可,當(dāng)然,除此之外還有許多細(xì)節(jié)問(wèn)題需要處理,由于文章篇幅的問(wèn)題,我們留到下篇文章再給大家介紹。


          我們的文章到此就結(jié)束啦,如果你喜歡今天的量化投資內(nèi)容,請(qǐng)持續(xù)關(guān)注二七阿爾量化。

          有任何問(wèn)題,可以在公眾號(hào)后臺(tái)回復(fù):加群,回答相應(yīng)紅字驗(yàn)證信息,進(jìn)入互助群詢問(wèn)。

          希望你能在下面點(diǎn)個(gè)贊和在看支持我繼續(xù)創(chuàng)作,謝謝!

          歡迎關(guān)注公眾號(hào):二七阿爾量化

          瀏覽 212
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  日本欧美中文 | 天堂8中文在线 | 网址成人视频国产偷拍 | 围产精品久久久久久 | 有限公司尻屄视频网站 |