基于货币对相关性计算回撤

Calculating Drawdown Based on Currency Pair Correlation

提问人:kbs 提问时间:8/28/2023 最后编辑:kbs 更新时间:8/29/2023 访问量:52

问:

该程序的目的是计算达到最大回撤的风险。 例如,如果我有一个投资组合,由风险为 1% 的欧元/美元和 1% 风险的英镑/美元组成,如果欧元/美元被止损,如果英镑/美元与欧元/美元正相关 1 倍,那么我将损失 2% 的账户余额,因为英镑/美元也会被止损。

实际上,货币的相关性是一个频谱,因此更现实的例子是:

#max drawdown with 3 positions, EUR/USD long with 2% risk, USD/JPY long with .5% risk, and EUR/JPY short at 1% risk
  #drawdown = -2% + (corr(pair1, pair2) * -.5) + (corr(pair1, pair3) * -1)
  #drawdown = -2% + (-0.220332 * -.5) + (0.29804 * -1)
  #drawdown = -2% + 0.110166 + -0.29804
  #drawdown = -2.19 % 

关于这一点的一些说明:

  1. 我的公式以“-2%”开头。这是因为欧元/美元被选为枢轴货币,而枢轴货币将始终与自身具有 1 的相关性,因此无需进行相关性计算。
  2. 每对之间的相关性乘以您承担风险的账户百分比。
  3. 它们加在一起产生最大回撤,这是另一种说法,“如果欧元/美元被止损,我将损失账户余额的 2%,但鉴于其他货币在某种程度上与欧元/美元相关,我的其他头寸会怎么做?

在上面,你可以看到我的“伪代码”,我在编程时遇到了麻烦。我只是不知道从哪里开始。

该计划需要 csv 格式的投资组合表:

pair,risk,direction
EUR/USD,2,long
USD/JPY,.5,long
EUR/JPY,1,short

以下是程序代码:

# %%
from twelvedata import TDClient
import os
import pandas as pd

# %%
td = TDClient(os.getenv('TD_API'))

# %%
all_symbols = ("AUD/CAD","AUD/CHF","AUD/JPY","AUD/NZD","AUD/USD",
               "CAD/CHF", "CAD/JPY", "CHF/JPY", 
               "EUR/AUD", "EUR/CAD", "EUR/CHF", "EUR/GBP", "EUR/JPY", "EUR/NZD", "EUR/USD",
               "GBP/AUD", "GBP/CAD", "GBP/CHF", "GBP/JPY", "GBP/NZD", "GBP/USD",
               "NZD/CAD", "NZD/CHF", "NZD/JPY", "NZD/USD", 
               "USD/CAD", "USD/CHF", "USD/JPY")

# %%
portfolio_sheet = pd.read_csv('portfolio_example.csv')
drawdown_tolerance = 4

# %%
for pair in portfolio_sheet['pair']:
    if pair in all_symbols:
      continue
    else:
      print("Symbol is not allowed or mispelled.  Please check the 'all_symbols' variable.")
      exit()

# %%
table = pd.DataFrame()

for _symbol in portfolio_sheet['pair']:
  ts = td.time_series(
    symbol = _symbol,
    interval="1day",
    outputsize="14"
  ).as_pandas()

  ts.drop(['open', 'high', 'low'], axis=1, inplace=True)
  ts.rename(columns={'close': str(_symbol)}, inplace=True)
  table = pd.concat([table, ts], axis=1)

print(table)
table = table.pct_change()
print(table)
print(table.corr())

# %%
#pseudo code:

#max drawdown with EUR/USD long 1% and USD/JPY long 1% in portfolio
  #drawdown = -1% + (corr(pair1, pair2) * -1%)
  #drawdown = -1% + (-0.187568) * -1%)
  #drawdown = -.81%

#max drawdown with 2 EUR/USD long positions at 1% risk each
  #drawdown = -1% + (corr(EUR/USD, EUR/USD) * -1%)
  #drawdown = -1% + (1.0 * -1%) 
  #drawdown = -2%

#max drawdown with 3 positions, EUR/USD long with 2% risk, USD/JPY long with .5% risk, and EUR/JPY short at 1% risk
  #drawdown = -2% + (corr(pair1, pair2) * -.5) + (corr(pair1, pair3) * -1)
  #drawdown = -2% + (-0.228452 * -.5) + (0.302295 * -1)
  #drawdown = -2% + 0.114226 + -0.302295
  #drawdown = -2.19 %

# %%
corr_counter = 1
pivot_risk = portfolio_sheet.iloc[0,1]
risk_counter = 2
drawdown = pivot_risk

# %%
for i in table.columns:
  for i in range(len(table.columns)-1):
    corr = table.iloc[:,0].corr(table.iloc[:,corr_counter])
    risk = corr * portfolio_sheet.iloc[risk_counter,1]
    if corr_counter < len(table.columns) -1:
      corr_counter += 1
  
  
  print("Risk is ",risk)
  print("Drawdown is ",drawdown)
  drawdown += risk
  print("Drawdown plus risk is ", drawdown)

  if risk_counter < len(portfolio_sheet) -1:
    risk_counter += 1 

编辑3:

所有打印报表合并产生:

(这只是价格数据)

            EUR/USD    USD/JPY    EUR/JPY
datetime                                 
2023-08-28  1.08170  146.50500  158.47000
2023-08-25  1.07950  146.45500  158.10500
2023-08-24  1.08100  145.83501  157.66000
2023-08-23  1.08630  144.84500  157.34000
2023-08-22  1.08450  145.89000  158.23000
2023-08-21  1.08960  146.21500  159.31000
2023-08-18  1.08720  145.39500  158.06000
2023-08-17  1.08720  145.83501  158.56000
2023-08-16  1.08795  146.34500  159.22000
2023-08-15  1.09040  145.58000  158.75000
2023-08-14  1.09060  145.55499  158.75999
2023-08-11  1.09460  144.96001  158.70000
2023-08-10  1.09820  144.75500  158.96001
2023-08-09  1.09750  143.72501  157.73199

(这是价格数据的百分比变化)

            EUR/USD   USD/JPY   EUR/JPY
datetime                                
2023-08-28       NaN       NaN       NaN
2023-08-25 -0.002034 -0.000341 -0.002303
2023-08-24  0.001390 -0.004233 -0.002815
2023-08-23  0.004903 -0.006789 -0.002030
2023-08-22 -0.001657  0.007215  0.005657
2023-08-21  0.004703  0.002228  0.006826
2023-08-18 -0.002203 -0.005608 -0.007846
2023-08-17  0.000000  0.003026  0.003163
2023-08-16  0.000690  0.003497  0.004162
2023-08-15  0.002252 -0.005227 -0.002952
2023-08-14  0.000183 -0.000172  0.000063
2023-08-11  0.003668 -0.004088 -0.000378
2023-08-10  0.003289 -0.001414  0.001638
2023-08-09 -0.000637 -0.007115 -0.007725

(这是相关表)

     EUR/USD   USD/JPY   EUR/JPY
EUR/USD  1.000000 -0.230169  0.299713
USD/JPY -0.230169  1.000000  0.859275
EUR/JPY  0.299713  0.859275  1.000000

(这是最后一个 for 循环的输出,这是不正确的,因为风险不能每次都是 .299。for 循环旨在执行与上面编写的伪代码相同的操作)

Risk is  0.29971261173598107
Drawdown is  2.0
Drawdown plus risk is  2.299712611735981
Risk is  0.29971261173598107
Drawdown is  2.299712611735981
Drawdown plus risk is  2.599425223471962
Risk is  0.29971261173598107
Drawdown is  2.599425223471962
Drawdown plus risk is  2.899137835207943

如您所见,最终的“回撤加风险”数字应该与伪代码中的数字相同,即 2.19。

Python Pandas 交易 量化金融

评论

0赞 itprorh66 8/29/2023
“# %% (this block is not working)” 是什么意思?它具体应该做什么,它做什么,什么表明结果不正确?
0赞 kbs 8/29/2023
添加了更多解释
0赞 kbs 8/29/2023
代码工作没有错误。我现在唯一担心的是我的相关表不正确。其他相关性表的英镑/美元和欧元/美元相关性为 90+,而我的相关性仅为 56。有什么建议吗?github.com/kirillmcclintock/fx_correlation_risk_management

答: 暂无答案