【问题标题】:Fill out dataframe by searching another dataframe by first testing for condition通过首先测试条件搜索另一个数据框来填充数据框
【发布时间】:2021-09-11 21:09:00
【问题描述】:

我正在尝试根据给定的购买日期测试不同的卖出简单移动平均线标准。

我有一个如下的购买数据数据库 (df_buy)。我想填写NaN 值。 (FCU = 首次收盘价)

  Symbol                Time  buy_price     LOD  date_FCU_10dMA  price_FCU_10dMA
0    AMD 2019-12-12 09:36:00      39.52   27.43             NaN              NaN
1    AMD 2020-01-16 09:33:00      49.21   27.43             NaN              NaN
2   BITF 2021-08-03 09:47:00       4.26    2.81             NaN              NaN
3   DOCN 2021-06-14 09:32:00      41.76   35.35             NaN              NaN
4   NVDA 2020-07-29 09:38:00     416.81  169.32             NaN              NaN
5   NVDA 2020-09-25 10:34:00     499.72  169.32             NaN              NaN
6   UPST 2021-02-09 09:32:00      76.83   22.61             NaN              NaN
7   UPST 2021-03-18 09:32:00      88.56   22.61             NaN              NaN

我有另一个数据库,其中包含每日库存数据如下 (df_day)

        Symbol                Time  Close   LOD   10MA    20MA
2722244   AEHR 2019-11-25 16:00:00   1.90  1.29  2.005  1.8870
2722289   AEHR 2019-11-26 16:00:00   1.92  1.29  2.032  1.8925
2722383   AEHR 2019-12-02 16:00:00   1.88  1.29  2.056  1.8985
2722435   AEHR 2019-12-03 16:00:00   1.88  1.29  2.046  1.8995
2722471   AEHR 2019-12-04 16:00:00   1.89  1.29  2.020  1.9055
2722569   AEHR 2019-12-06 16:00:00   1.93  1.29  1.993  1.9140

根据策略,首次收盘必须在买入日期后至少 2 天。


df_filt2['price_FCU_10dMA'] = (df_buy['buy_price'] > df_day['20MA'])
Error: ValueError: Can only compare identically-labeled Series objects


for i, row in df_buy.iterrows():
    # drop unlisted symbols
    filt1 = (df_day['Symbol'] != df_buy['Symbol'].loc[i])
    df_filt1 = df_day.drop(index=df_day[filt1].index)

    # drop trades from before buy date + 2
    filt2 = (pd.to_datetime(df_day['Time']) < (pd.to_datetime(df_buy['Time'].loc[i] + pd.to_timedelta(2, unit='d'))))
    df_filt2 = df_filt1.drop(index=df_filt1[filt2].index)
    # sort values
    df_filt2.sort_values(by=['Symbol', 'Time'], inplace=True)

    # drop rows where Close is above the 10MA
    df_filt2['price_FCU_10dMA'] = (df_buy['buy_price'] > df_day['20MA'])
    filt3 = (df_filt2['price_FCU_10dMA'] == False)

    # trail_sell = df_filt2[filt3].loc[10]
    df_buy['price_FCU_10dMA'].loc[i] = df_filt2.loc[filt3, 'Close'].iloc[0]  # returns the single value of first close under 10ma
    df_buy['date_FCU_10dMA'].loc[i] = df_filt2.loc[filt3, 'Time'].iloc[0]  # returns the single value of first close under 10ma

【问题讨论】:

    标签: pandas dataframe stock ohlc


    【解决方案1】:

    您可以在一个逻辑语句中组合所有 3 个条件:

    two_days = pd.to_timedelta('2d')
    no_match = pd.Series({'Time': np.nan, 'Close': np.nan})
    
    for i, row in df_buy.iterrows():
        cond = (
            (df_day['Symbol'] == row['Symbol']) &
            (df_day['Time'] > row['Time'] + two_days) &
            (df_day['Close'] < df_day['10MA'])
        )
        match = no_match if not cond.any() else df_day[cond].head(1)
        df_buy.loc[i, ['price_FCU_10dMA', 'date_FCU_10dMA']] = match[['Close', 'Time']]
    

    【讨论】:

    • 感谢@Code Different。这更加优雅,但是,仍然存在一个问题:df_day[cond].head(1)(倒数第二行)返回正确的行,但是,这些值没有被填充到所需的列中
    • 尝试用 iloc[0] 替换 head(1)
    • 我将df_buy.loc[i, ['price_FCU_10dMA', 'date_FCU_10dMA']] = match[['Close', 'Time']] 拆分为df_buy.loc[i, 'price_FCU_10dMA'] = match['Close']df_buy.loc[i, 'date_FCU_10dMA'] = match['Time'],现在它可以工作了。干杯
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-09
    • 2018-12-08
    • 1970-01-01
    • 2020-09-16
    • 1970-01-01
    相关资源
    最近更新 更多