iT邦幫忙

2024 iThome 鐵人賽

DAY 19
0
AI/ ML & Data

打開就會 AI 與數據分析的投資理財術系列 第 19

Day18:強化學習在交易中的應用--使用 Stable Baselines 和 FinRL

  • 分享至 

  • xImage
  •  

在上一節中我們仔細講過了 RL 的細節以及 from scratch 的實做了整個 pipeline。在本節中,我們將學習如何使用強化學習庫 Stable Baselines 和金融強化學習庫 FinRL,來開發股票交易機器人。我們將比較多種常見的強化學習算法,如 DQN、PPO、A2C 等,並在實驗中分析它們的性能差異。我們還將繪製買賣點、年化收益、總獎勵-訓練回合等圖形,以直觀地評估模型的表現。那由於今日同時比較了3個模型,具體詳細跑得結果就請看今日 Colab,我這邊只放程式這樣不會太亂。


一、引言

1. 強化學習在金融交易中的應用

  • 自適應策略:強化學習能夠學習環境的特性,自主決策買賣行為,適應市場變化。
  • 長期收益最大化:目標是通過累積獎勵,實現長期收益的最大化,符合投資的核心目標。

2. 庫介紹

  • Stable Baselines3:一個基於 Pytorch 的強化學習庫,實現了多種常見的強化學習算法,易於使用和擴展。官方連結
    https://ithelp.ithome.com.tw/upload/images/20241001/20120549bxODVnMlRs.png
  • FinRL:一個專門為金融強化學習設計的庫,內置了多種市場環境、數據處理工具和策略評估方法。官方連結
    https://ithelp.ithome.com.tw/upload/images/20241001/20120549hHotTHvQjr.png

二、環境設置

1. 安裝必要的庫

!pip install stable-baselines3[extra]
!pip install finrl
!pip install yfinance
!pip install pandas numpy matplotlib
!pip install alpaca-trade-api
!pip install exchange_calendars
!pip install stockstats
!pip install wrds

for FinRL:

## install required packages
!pip install swig
!pip install wrds
!pip install pyportfolioopt
## install finrl library
!pip install -q condacolab
import condacolab
condacolab.install()
!apt-get update -y -qq && apt-get install -y -qq cmake libopenmpi-dev python3-dev zlib1g-dev libgl1-mesa-glx swig
!pip install git+https://github.com/AI4Finance-Foundation/FinRL.git

for TA-Lib:

!wget http://prdownloads.sourceforge.net/ta-lib/ta-lib-0.4.0-src.tar.gz
!tar -xzvf ta-lib-0.4.0-src.tar.gz
%cd ta-lib
!./configure --prefix=/usr
!make
!make install
!pip install Ta-Lib

2. 導入庫

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import yfinance as yf
from finrl.meta.env_stock_trading.env_stocktrading import StockTradingEnv
from stable_baselines3 import DQN, PPO, A2C
from stable_baselines3.common.vec_env import DummyVecEnv
from stable_baselines3.common.evaluation import evaluate_policy

三、數據準備

1. 獲取股票數據

我們將使用 yfinance 來下載蘋果公司(AAPL)的歷史數據。

data = yf.download('AAPL', start='2015-01-01', end='2021-01-01')
data.reset_index(inplace=True)
data = data[['Date', 'Open', 'High', 'Low', 'Close', 'Adj Close', 'Volume']]

2. 特徵工程

在強化學習中,我們可以添加一些技術指標作為狀態特徵,提升代理的決策能力。

import talib

# 添加技術指標
data['MA5'] = talib.SMA(data['Close'], timeperiod=5)
data['MA10'] = talib.SMA(data['Close'], timeperiod=10)
data['RSI'] = talib.RSI(data['Close'], timeperiod=14)
data['MACD'], data['MACD_signal'], data['MACD_hist'] = talib.MACD(data['Close'])
data['tic'] = 'AAPL'

3. 處理缺失值

data.fillna(method='bfill', inplace=True)

四、構建交易環境

1. 定義環境配置

stock_dimension = 1
state_space = stock_dimension * (5 + 3)  # 5個價格 + 3個技術指標
action_space = stock_dimension

2. 建立環境

# 將數據按照日期排序
data.sort_values('Date', inplace=True)

# 定義環境參數
env_kwargs = {
    "stock_dim": stock_dimension,
    "hmax": 100,  # 每次交易的最大股票數量
    "initial_amount": 100000,  # 初始資金
    "buy_cost_pct": 0.001,  # 買入手續費
    "sell_cost_pct": 0.001,  # 賣出手續費
    "state_space": state_space,
    "action_space": action_space,
    "reward_scaling": 1e-4,
    "tech_indicator_list": ['MA5', 'MA10', 'RSI', 'MACD', 'MACD_signal', 'MACD_hist'],
    "print_verbosity": 0,
    "num_stock_shares":1
}

# 重命名列
data.rename(columns={'Date': 'date', 'Open': 'open', 'High': 'high', 'Low': 'low',
                     'Close': 'close', 'Adj Close': 'adj_close', 'Volume': 'volume'}, inplace=True)


# 分割訓練和測試數據
train = data.iloc[:int(0.8*len(data))].copy().reset_index(drop=True)
test = data.iloc[int(0.8*len(data)):].copy().reset_index(drop=True)

# 創建訓練環境
train_env = StockTradingEnv(df=train, **env_kwargs)
train_env = DummyVecEnv([lambda: train_env])

# 創建測試環境
test_env = StockTradingEnv(df=test, **env_kwargs)
test_env = DummyVecEnv([lambda: test_env])

五、選擇和訓練強化學習算法

我們將比較三種常見的強化學習算法:DQN、PPO 和 A2C。

1. 定義訓練函數

def train_agent(env, model_class, model_name, timesteps=10000):
    model = model_class('MlpPolicy', env, verbose=0)
    model.learn(total_timesteps=timesteps)
    model.save(f"{model_name}_model")
    return model

2. 訓練 DQN

dqn_model = train_agent(train_env, DQN, "DQN", timesteps=10000)

3. 訓練 PPO

ppo_model = train_agent(train_env, PPO, "PPO", timesteps=10000)

4. 訓練 A2C

a2c_model = train_agent(train_env, A2C, "A2C", timesteps=10000)

六、評估和比較模型

1. 定義評估函數

def evaluate_agent(env, model):
    obs = env.reset()
    done = False
    total_reward = 0
    rewards = []
    net_worths = []
    while not done:
        action, _states = model.predict(obs)
        obs, reward, done, info = env.step(action)
        total_reward += reward[0]
        rewards.append(reward[0])
        net_worths.append(env.envs[0].portfolio_value)
    return total_reward, rewards, net_worths

2. 評估 DQN

dqn_total_reward, dqn_rewards, dqn_net_worths = evaluate_agent(test_env, dqn_model)

3. 評估 PPO

ppo_total_reward, ppo_rewards, ppo_net_worths = evaluate_agent(test_env, ppo_model)

4. 評估 A2C

a2c_total_reward, a2c_rewards, a2c_net_worths = evaluate_agent(test_env, a2c_model)

七、結果分析

1. 比較總獎勵

print(f"DQN Total Reward: {dqn_total_reward}")
print(f"PPO Total Reward: {ppo_total_reward}")
print(f"A2C Total Reward: {a2c_total_reward}")

2. 繪製資產淨值曲線

plt.figure(figsize=(12,6))
plt.plot(dqn_net_worths, label='DQN')
plt.plot(ppo_net_worths, label='PPO')
plt.plot(a2c_net_worths, label='A2C')
plt.title('Agent Net Worth Over Time')
plt.xlabel('Time Step')
plt.ylabel('Net Worth')
plt.legend()
plt.show()

3. 繪製總獎勵曲線

plt.figure(figsize=(12,6))
plt.plot(np.cumsum(dqn_rewards), label='DQN')
plt.plot(np.cumsum(ppo_rewards), label='PPO')
plt.plot(np.cumsum(a2c_rewards), label='A2C')
plt.title('Cumulative Reward Over Time')
plt.xlabel('Time Step')
plt.ylabel('Cumulative Reward')
plt.legend()
plt.show()

4. 計算年化收益率

def calculate_annual_return(net_worths, initial_amount, days):
    total_return = (net_worths[-1] - initial_amount) / initial_amount
    annual_return = ((1 + total_return) ** (252 / days)) - 1
    return annual_return

test_days = len(test)
dqn_annual_return = calculate_annual_return(dqn_net_worths, env_kwargs['initial_amount'], test_days)
ppo_annual_return = calculate_annual_return(ppo_net_worths, env_kwargs['initial_amount'], test_days)
a2c_annual_return = calculate_annual_return(a2c_net_worths, env_kwargs['initial_amount'], test_days)

print(f"DQN Annual Return: {dqn_annual_return:.2%}")
print(f"PPO Annual Return: {ppo_annual_return:.2%}")
print(f"A2C Annual Return: {a2c_annual_return:.2%}")

八、繪製買賣點

1. 定義函數繪製交易動作

def plot_actions(data, actions):
    data = data.iloc[int(0.8*len(data)):]
    data.reset_index(inplace=True, drop=True)
    buy = []
    sell = []
    for i in range(len(actions)):
        if actions[i] == 1:  # 買入
            buy.append(data['Close'].iloc[i])
            sell.append(np.nan)
        elif actions[i] == 2:  # 賣出
            buy.append(np.nan)
            sell.append(data['Close'].iloc[i])
        else:
            buy.append(np.nan)
            sell.append(np.nan)
    plt.figure(figsize=(12,6))
    plt.plot(data['Close'], label='Close Price')
    plt.scatter(data.index, buy, label='Buy', marker='^', color='g')
    plt.scatter(data.index, sell, label='Sell', marker='v', color='r')
    plt.title('Trading Actions')
    plt.xlabel('Time Step')
    plt.ylabel('Price')
    plt.legend()
    plt.show()

2. 獲取代理的交易動作

def get_actions(env, model):
    obs = env.reset()
    done = False
    actions = []
    while not done:
        action, _states = model.predict(obs)
        actions.append(action[0])
        obs, reward, done, info = env.step(action)
    return actions

3. 繪製 DQN 的交易動作

dqn_actions = get_actions(test_env, dqn_model)
plot_actions(test, dqn_actions)

4. 繪製 PPO 的交易動作

ppo_actions = get_actions(test_env, ppo_model)
plot_actions(test, ppo_actions)

5. 繪製 A2C 的交易動作

a2c_actions = get_actions(test_env, a2c_model)
plot_actions(test, a2c_actions)

九、總結

1. 模型性能比較

  • 總獎勵:比較各模型在測試集上的累積獎勵。
  • 資產淨值曲線:觀察資產淨值的變化趨勢,評估模型的資產增值能力。
  • 年化收益率:計算各模型的年化收益率,衡量長期投資回報。

2. 交易行為分析

  • 買賣點:通過繪製交易動作,直觀地了解模型的交易決策。
  • 交易頻率:評估模型的交易頻率,避免過度交易。

3. 結論

  • 模型選擇:根據實驗結果,選擇表現最優的模型作為交易策略。
  • 改進方向:調整模型參數、增加特徵、優化環境設計等,進一步提升模型性能。

十、作業

  1. 嘗試其他強化學習算法:如 SAC、TD3 等,觀察其在交易任務中的表現。
  2. 增加交易標的:將單個股票擴展為多個股票組合,測試模型的資產配置能力。
  3. 引入風險控制:在環境或獎勵函數中加入風險約束,如最大回撤、夏普比率等。
  4. 優化模型參數:調整模型的超參數,如學習率、神經網絡結構、訓練步數等,尋找最佳配置。

提示

  • 數據質量:確保數據的完整性,處理缺失值和異常值。
  • 特徵工程:添加更多有用的技術指標,提高模型的決策能力。
  • 模型穩定性:進行多次實驗,檢驗模型的穩定性和泛化能力。
  • 實際因素:考慮交易成本、滑點等實際交易中的因素,增強模型的實用性。

注意事項

  • 風險提示:金融市場具有高度的不確定性,模型的預測結果僅供參考,不應作為實際投資決策的唯一依據。
  • 合規要求:遵守相關法律法規和市場規則,合法合規地進行交易。
  • 倫理考慮:確保模型的設計和應用符合道德標準,不得進行市場操縱等不當行為。

Ref.

1.https://stable-baselines.readthedocs.io/en/master/
2.https://finrl.readthedocs.io/en/latest/index.html


上一篇
Day17:強化學習在交易中的應用--基礎打底
下一篇
Day19:強化學習在交易中的應用--結合 Stable Baselines 進 Backtrader
系列文
打開就會 AI 與數據分析的投資理財術30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言