iT邦幫忙

2023 iThome 鐵人賽

DAY 27
0
AI & Data

從零到英雄:用GCP建立AI交易體系系列 第 27

Day 27 回測統計(二)

  • 分享至 

  • xImage
  •  

先延續昨天的內容,我們寫一下算平均持倉時間的程式之後用得上~
今天內容不多,因為我在台南玩XD

從目標位置推導交易的時間點:

# 定義目標位置為0的索引
df0 = tPos[tPos == 0].index

# 將目標位置序列向下移動一個位置,找出非0的索引
df1 = tPos.shift(1)
df1 = df1[df1 != 0].index

# 找出需要平倉(變為平倉狀態)的時機
bets = df0.intersection(df1)  # 平倉時機

# 計算連續兩個目標位置的乘積,找出其變號(翻轉)的索引
df0 = tPos.iloc[1:] * tPos.iloc[:-1].values
bets = bets.union(df0[df0 < 0].index).sort_values()  # 加入變號時機

# 確保最後一個賭注被包含在內
if tPos.index[-1] not in bets:
    bets = bets.append(tPos.index[-1:])  # 加入最後一個賭注

計算平均持倉時間:

def getHoldingPeriod(tPos):
    # 使用平均進場時間配對算法來推導平均持有期(以天為單位)
    hp, tEntry = pd.DataFrame(columns=['dT', 'w']), 0.0

    # 計算目標位置和時間的差值
    pDiff = tPos.diff()
    tDiff = (tPos.index - tPos.index[0]) / np.timedelta64(1, 'D')

    for i in xrange(1, tPos.shape[0]):
        # 如果目標位置增加或不變
        if pDiff.iloc[i] * tPos.iloc[i - 1] >= 0:  
            if tPos.iloc[i] != 0:
                tEntry = (tEntry * tPos.iloc[i - 1] + tDiff[i] * pDiff.iloc[i]) / tPos.iloc[i]
        else:  # 目標位置減少
            # 如果目標位置發生變號(翻轉)
            if tPos.iloc[i] * tPos.iloc[i - 1] < 0:  
                hp.loc[tPos.index[i], ['dT', 'w']] = (tDiff[i] - tEntry, abs(tPos.iloc[i - 1]))
                tEntry = tDiff[i]  # 重設進場時間
            else:
                hp.loc[tPos.index[i], ['dT', 'w']] = (tDiff[i] - tEntry, abs(pDiff.iloc[i]))

    # 計算加權平均持有期
    if hp['w'].sum() > 0:
        hp = (hp['dT'] * hp['w']).sum() / hp['w'].sum()
    else:
        hp = np.nan  # 如果沒有有效的權重,則設為NaN

    return hp

績效

績效統計是不考慮風險調整的收益。一些有用的績效指標像是:

  • PnL:在整個回測期間(包括回測結束後產生的清算成本)產生的總金額。
  • 來自多頭倉位的 PnL:僅由多頭倉位產生的PnL金額部分。這是評估多空、盤整策略偏見的特化值。
  • 年化收益率:包括股息、配股、成本等在內的時間加權平均年收益率。
  • 命中率:產生正PnL的賭注的比例。
  • 平均收益(命中):產生利潤的賭注的平均收益。
  • 平均收益(失誤):產生損失的賭注的平均收益。

上一篇
Day 26 回測結果統計(一)
下一篇
Day 28 堅持得有點辛苦之一定不只30天
系列文
從零到英雄:用GCP建立AI交易體系34
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言