使用Pandas Python中的2个单独DateFrame计算每月价格收益

时间:2017-04-02 03:26:52

标签: python pandas datetime

我正在尝试计算用户股票市场交易的价格收益。

我有2个DataFrames:

第一个有购买数据。这被称为'购买'。以下示例。

Acceptance_Date Symbol  Username    Volume
01-Jan-2017       FB      John       423
01-Jan-2017       FB      Lucy       58
01-Jan-2017       FB      Jeff       49,548

第二个有股市数据。这被称为“市场”。以下示例。

Symbol  Date    Open    Close
FB    1-Jan-16  80.00   81.00
FB    1-Apr-16  90.00   91.00
FB    1-Jul-16  100.00  101.00
FB    1-Jan-17  110.00  110.00

我想计算每次购买的1个月,3个月,6个月和12个月的表现。

因此逻辑应该是:如果用户在2016年1月1日购买,2016年4月1日该股票的价值涨幅是多少?

输出应该是更新的购买数据框,如下所示:

Acceptance_Date Symbol  Username    Volume   one_month  two_month
01-Jan-2017       FB      John       423         x%         x%
01-Jan-2017       FB      Lucy       58          x%         x%
01-Jan-2017       FB      Jeff       49,548      x%         x%

我觉得我以极其低效的方式解决这个问题。我可以在2分钟内在Excel中粉碎它,但我很难在Python / Pandas(我是新手)中解决它。

这是我尝试的代码,感觉就像在钥匙上砸碎了一块石头。请帮忙!

#create a df to combine purchase data and market data
purchase_df = pd.merge(market[['Symbol', 'Date', 'Close']], 
    buys[['Symbol', 'Acceptance_Date']], 
    left_on=['Symbol', 'Date'], right_on=['Symbol', 'Acceptance_Date'])

#create a new column "one_month" and add the purchase date plus one month
one_month = pd.to_datetime(buys['Acceptance_Date'], format='%Y-%m-%d').dt.date + relativedelta(months =+ 1)
buys['one_month'] = one_month

#merge purchase_df with the one_month price data 
month_forward = pd.merge(market[['Symbol', 'Date', 'Close']], 
    buys[['Symbol', 'one_month']], 
    left_on=['Symbol', 'Date'], right_on=['Symbol', 'one_month'])

#calculate the gain
one_month_gain = (month_forward.close - purchase_df.close) / purchase_df.close

#repeat again for months 3, 6 and 12 then merge

2 个答案:

答案 0 :(得分:0)

这就是我要做的事情:

首先转动您的市场表,以便将符号作为索引,将日期作为列:

# assuming you are using close-to-close returns
market_pivot = market.pivot_table(index='Symbol', columns='Date', values='Close')

其次,定义一个获得回报的函数:

def get_return(ser, li_duration):
    """
    ser : pandas series, represents a row from purchase_df
    li_duration : list of int for holding periods
    """
    # do some list comprehension here to convert li_duration to end dates
    ldt_dates = [...]
    date = ser['Acceptance_Date']
    symbol = ser['Symbol']
    begin_price = market_pivot.loc[symbol, date]
    end_price = market_pivot.loc[symbol, ldt_dates]
    # calculate returns and replace the indices
    return_ser = end_price / begin_price - 1
    return_ser.index = [<desired column labels here>]
    # append the returns to purchase information
    return ser.append(return_ser)

现在逐行将此函数应用于purchase_df:

df_result = purchase_df.apply(get_return, li_duration=[1, 3, 6, 12])
  

免责声明:没有实际运行代码,只是为了展示思维过程

答案 1 :(得分:0)

我最终找到了最简单的答案:

#shift the data up one cell
new_market['one_m_close'] = new_market['close'].shift(-22)
new_market['one_m_date'] = new_market['date'].shift(-22)

#calculate the gain
new_market['one_m_change'] = (new_market.one_m_close - new_market.close) / new_market.close

#then merge DataFrames with pd.merge