【问题标题】:Problem iteration columns and rows Dataframe问题迭代列和行数据框
【发布时间】:2020-10-16 11:36:03
【问题描述】:

这是我的问题:

假设您必须在以下条件下买卖两个对象:

  1. 如果对象 A 或 B 的价格低于 150 (如果第二天对象仍然低于 150,那么您只需保留该对象,什么都不做
  2. 如果对象高于或等于 150,则您卖出该对象并获利

你以 10000 美元开始游戏

这是包含所有价格的 DataFrame

df=pd.DataFrame({'Date':['2017-05-19','2017-05-22','2017-05-23','2017-05-24','2017-05-25','2017-05-26','2017-05-29'],
                 'A':[153,147,149,155,145,147,155],
                 'B':[139,152,141,141,141,152,152],})

df['Date']=pd.to_datetime(df['Date'])
df = df.set_index('Date')

目标是返回一个 DataFrame,其中包含您持有的 A 和 B 的对象数量以及您剩余的现金数量。 如果满足条件,每个物品的分配是您没有任何物品的现金的一半(重量=1/2),如果您已经有一个物品(重量=1),则为剩余的现金

我们先看df,我还将开发我正在尝试创建的新数据框(我们称之为df_end):

在 2017 年 5 月 19 日,对象 A 为 153 美元,B 为 139 美元:您购买了 35.97 个对象 B (=5000/139),因为价格为 您还剩 5000 美元现金。

在 2017 年 5 月 22 日,对象 A 为 147 美元,B 为 152 美元:您以 =150 --> 由于出售 B,您现在有 5467,44$ 现金。

在 2017 年 5 月 23 日,对象 A 为 149 美元,B 为 141 美元:您保持在对象 A(34.01 对象)上的头寸,因为它仍低于 150,您买入 38.77 对象 B(=5467.44/141)作为价格是 你现在还有 0 美元现金。

在 2017 年 5 月 24 日,对象 A 为 155 美元,B 为 141 美元:您以 155 美元的价格卖出 34.01 个对象 A,因为它高于 150 美元,您保留 38.77 个对象 B,因为它仍然低于 150 —> 您现在有由于出售 A,剩下 5271.55 美元的现金

在 2017 年 5 月 25 日,对象 A 为 145 美元,B 为 141 美元:您购买 36.35 个对象 A (5271.55/145),因为它低于 150,您保留 38.77 个对象 B,因为它仍然低于 150 —> 你有现在0美元现金

在 2017 年 5 月 26 日,对象 A 为 147 美元,B 为 152 美元:您以 152 的价格卖出 38.77 个对象 B,因为它高于 150,您保留 36.35 个对象 A,因为它仍然低于 150 —> 您现在有 5893.04 美元由于出售对象 B 以现金支付

在 2017 年 5 月 29 日,对象 A 为 155 美元,B 为 152 美元:您以 155 的价格卖出 36.35 个对象 A,因为它高于 150,而您什么也不做,因为 B 不低于 150 —> 您现在有 11.527,出售对象 A 获得 29 美元现金。

因此,新的数据框 df_end 应该如下所示(这是我要寻找的结果)

               A     B    Cash
Date        
2017-05-19   0      35.97  5000
2017-05-22   34.01  0      5467.64
2017-05-23   34.01  38.77  0
2017-05-24   0      38.77  5272.11
2017-05-25   36.35  38.77  0    
2017-05-26   36.35  0      5893.04
2017-05-29   0      0      11527.29

我的主要问题是我们必须遍历行和列,这是最困难的部分。 一个星期以来我一直在努力寻找解决方案,但我仍然没有找到任何想法,这就是为什么我试图尽可能清楚地解释。

因此,如果有人对此问题有任何想法,非常欢迎您。 非常感谢

【问题讨论】:

    标签: python pandas loops dataframe if-statement


    【解决方案1】:

    你可以试试这个:

    import pandas as pd
    
    df=pd.DataFrame({'Date':['2017-05-19','2017-05-22','2017-05-23','2017-05-24','2017-05-25','2017-05-26','2017-05-29'],
                     'A':[153,147,149,155,145,147,155],
                     'B':[139,152,141,141,141,152,152],})
    
    df['Date']=pd.to_datetime(df['Date'])
    df = df.set_index('Date')
    
    print(df)
    
    #Values before iterations
    EntryCash=10000
    newdata=[]
    holding=False
    
    
    
    #First iteration  (Initial conditions)
    firstrow=df.to_records()[0]
    possibcash=EntryCash if holding else EntryCash/2
    prevroa=possibcash/firstrow[1] if firstrow[1]<=150 else 0
    prevrob=possibcash/firstrow[2] if firstrow[2]<=150 else 0 
    holding=any(i!=0 for i in [prevroa,prevrob])
    newdata.append([df.to_records()[0][0],prevroa,prevrob,possibcash])
    
    #others iterations
    for row in df.to_records()[1:]:
        possibcash=possibcash if holding else possibcash/2
        a=row[1]
        b=row[2]
        if a>150:
            if prevroa>0:
                possibcash+=prevroa*a
                a=0
            else:
                a=prevroa
        else:
            if prevroa==0:
                a=possibcash/a
                possibcash=0
            else:
                a=prevroa
        if b>150:
            if prevrob>0:
                possibcash+=prevrob*b
                b=0
            else:
                b=prevrob
        else:
            if prevrob==0:
                b=possibcash/b
                possibcash=0
            else:
                b=prevrob
        prevroa=a
        prevrob=b
        newdata.append([row[0],a,b,possibcash])
        holding=any(i!=0 for i in [a,b])
        
    
    df_end=pd.DataFrame(newdata, columns=[df.index.name]+list(df.columns)+['Cash']).set_index('Date')
    print(df_end)
    

    输出:

    df
                  A    B
    Date                
    2017-05-19  153  139
    2017-05-22  147  152
    2017-05-23  149  141
    2017-05-24  155  141
    2017-05-25  145  141
    2017-05-26  147  152
    2017-05-29  155  152
    
    df_end
                        A          B          Cash
    Date                                          
    2017-05-19   0.000000  35.971223   5000.000000
    2017-05-22  34.013605   0.000000   5467.625899
    2017-05-23  34.013605  38.777489      0.000000
    2017-05-24   0.000000  38.777489   5272.108844
    2017-05-25  36.359371  38.777489      0.000000
    2017-05-26  36.359371   0.000000   5894.178274
    2017-05-29   0.000000   0.000000  11529.880831
    

    如果要四舍五入到小数点后两位,可以加上:

    df_end=df_end.round(decimals=2)
    df_end:
                    A      B      Cash
    Date                              
    2017-05-19   0.00  35.97   5000.00
    2017-05-22  34.01   0.00   5467.63
    2017-05-23  34.01  38.78      0.00
    2017-05-24   0.00  38.78   5272.11
    2017-05-25  36.36  38.78      0.00
    2017-05-26  36.36   0.00   5894.18
    2017-05-29   0.00   0.00  11529.88
    

    最终值略有不同

    它与您想要的输出略有不同,因为有时您将值四舍五入到小数点后两位,而有时您没有。例如: 在你的第二行你放:

    #second row
    2017-05-22   34.01  0      5467.64
    

    这意味着您使用了对象 A 第一行的完整值,即 35.971223 而不是 35.97

    35.97*152
    Out[120]: 5467.44
    
    35.971223*152
    Out[121]: 5467.6258960000005  #---->closest to 5467.64
    

    在第 3 行,您再次使用了实际值,而不是四舍五入:

    #row 3
    2017-05-24   0      38.77  5272.11
    
    #Values
    34.013605*155
    Out[122]: 5272.108775
    
    34.01*155
    Out[123]: 5271.549999999999
    

    最后,我猜在最后两行你使用了四舍五入的值,因为:

    #last two rows
    2017-05-26   36.35  0      5893.04
    2017-05-29   0      0      11527.29
    
    #cash values
    
    #penultimate row, cash value
    38.777489*152
    Out[127]: 5894.178328
    
    38.77*152
    Out[128]: 5893.040000000001
    
    #last row, cash value
    5894.04+(155*36.35)
    Out[125]: 11528.29  #---->closest to 11527.29
    
    5894.04+(155*36.359371)
    Out[126]: 11529.742505
    

    【讨论】:

      猜你喜欢
      • 2018-08-21
      • 1970-01-01
      • 1970-01-01
      • 2019-09-29
      • 1970-01-01
      • 2014-11-25
      • 1970-01-01
      • 2020-06-05
      • 1970-01-01
      相关资源
      最近更新 更多