Python、Pands、股票组合滚动价值时间序列发行

2024-06-03 08:12:03 发布

您现在位置:Python中文网/ 问答频道 /正文

我用Python创建了一个timeseries,用于计算每个给定日期的滚动投资组合市场价值。时间序列现在看起来是这样的(总数是NHY.OL和YAR.OL的总和)

tickers     NHY.OL  YAR.OL   total
date                              
2020-07-27    0.00   763.60  763.60
2020-07-28   26.49   764.80  791.29
2020-07-29   26.39   755.80  782.19
2020-07-30   25.05   744.00  769.05
2020-07-31   25.42   380.70  406.12

这个时间序列由一个仓位表和一个包含股票收盘价的数据集组成,仓位表是动态的,这意味着它将从Django模型中收集数据,用户可以在其投资组合中输入他们的持有量,因此提供的这个数据集是解决我遇到的这个问题的一个简单示例

职位表:

         Date Direction  Ticker  Price  Volume  FX-rate  Comission  Short  Cost-price
0  2020-07-27       Buy  YAR.OL  381.0   2      1.0        0.0  False       381.0
1  2020-07-31      Sell  YAR.OL  380.0  -1      1.0        0.0  False      -380.0

[2 rows x 9 columns]
         Date Direction  Ticker  Price  Volume  FX-rate  Comission  Short  Cost-price
2  2020-07-28       Buy  NHY.OL   26.5   1      1.0        0.0  False        26.5

日终股价数据集:

            NHY.OL  YAR.OL
date                      
2020-07-27   26.35   381.8
2020-07-28   26.49   382.4
2020-07-29   26.39   377.9
2020-07-30   25.05   372.0
2020-07-31   25.42   380.7

然而,滚动投资组合价值中的初始价格是错误的。例如,在2020年7月27日,用户购买了381股股票,因此市值应该是762。投资组合的价值不是由买入价计算的,而是由市场收盘价计算的

我如何修复这个问题,使最终产品看起来更像这样

我希望它看起来怎么样:

tickers     NHY.OL  YAR.OL   total
date                              
2020-07-27   0.00    762.0   762.0
2020-07-28   26.50   764.80  791.30
2020-07-29   26.39   755.80  782.19
2020-07-30   25.05   744.00  769.05
2020-07-31   25.42   380.70  406.12

StackOverflow的一位优秀程序员帮我完成了这段代码。指向该线程的链接:Python pandas, stock portfolio value timeseries

代码

from io import StringIO
import pandas as pd

# create data frame with closing prices
data = '''date YAR.OL NHY.OL
2020-07-27  381.799988  26.350000
2020-07-28  382.399994  26.490000
2020-07-29  377.899994  26.389999
2020-07-30  372.000000  25.049999
2020-07-31  380.700012  25.420000
'''
closing_prices = (pd.read_csv(StringIO(data), 
                             sep='\s+', engine='python', 
                             parse_dates=['date']
                            )
                  .set_index('date')
                  .sort_index()
                  .sort_index(axis=1)
                 )
print(closing_prices.round(2))

输出:

           NHY.OL  YAR.OL
date                      
2020-07-27   26.35   381.8
2020-07-28   26.49   382.4
2020-07-29   26.39   377.9
2020-07-30   25.05   372.0
2020-07-31   25.42   380.7

定义位置表:

positions = [
    ('YAR.OL', '2020-07-27',  2),
    ('YAR.OL', '2020-07-31', -1),
    ('NHY.OL', '2020-07-28',  1),
]
# changed cost_price to volume
positions = pd.DataFrame(positions, columns=['tickers', 'date', 'volume'])
positions['date'] = pd.to_datetime(positions['date'])

positions = (positions.pivot(index='date', columns='tickers', values='volume')
             .sort_index()
             .sort_index(axis=1)
            )
positions = positions.reindex( closing_prices.index ).fillna(0).cumsum()
print(positions)

输出:

tickers     NHY.OL  YAR.OL
    date                      
    2020-07-27     0.0     2.0  # <-- these are transaction volumes
    2020-07-28     1.0     2.0
    2020-07-29     1.0     2.0
    2020-07-30     1.0     2.0
    2020-07-31     1.0     1.0

计算投资组合价值:

port_value = positions * closing_prices
port_value['total'] = port_value.sum(axis=1)
print(port_value.round(2))

目前的最终投资组合价值:

tickers     NHY.OL  YAR.OL   total
date                              
2020-07-27    0.00   762.00  763.6
2020-07-28   26.49   764.80  791.29
2020-07-29   26.39   755.80  782.19
2020-07-30   25.05   744.00  769.05
2020-07-31   25.42   380.70  406.12 

总而言之:目标是在添加新头寸时,用于计算当时市场价值的价格将取自头寸表价格列。 例:

Date         Calculation comment     Calculation
2020-07-27 - Volume * Price paid     2 * 381
2020-07-28 - Volume * Market price   2* 282.4
....
If a user buys more shares of the same stock then for the day they bouth it, it would be: (New volume * prie paid)+(Previous volume * Market price)
....
Date          Calculation comment                                       Calculation
2020-07-29 - (New volume * prie paid)+(Previous volume * Market price) (1* 380) + (2 * 377.9)
2020-07-30 - Volume * Market price                                      3 * 372.0

Tags: dateindexvaluepricetotalprices价值closing