Я расширил ваши образцы данных, чтобы иметь 2 длинных значения PnL, и изменил столбец date на DateTime :
df = pd.DataFrame(data=[
[ '24/2/2019', 4124.25, 0, 0, 0, 0 ],
[ '25/2/2019', 4130.67, 0, 0, 0, 0 ],
[ '26/2/2019', 4145.67, 1, 0, 0, 0 ],
[ '27/2/2019', 4180.10, 0, 0, 0, 0 ],
[ '28/2/2019', 4200.05, 0, 0, 0, 0 ],
[ '1/3/2019', 4210.12, 0, 1, 0, 0 ],
[ '2/3/2019', 4198.10, 0, 0, 0, 0 ],
[ '3/3/2019', 4210.34, 0, 0, 0, 0 ],
[ '4/3/2019', 4100.12, 0, 0, 1, 0 ],
[ '5/3/2019', 4219.23, 0, 0, 0, 1 ],
[ '6/3/2019', 4210.00, 1, 0, 0, 0 ],
[ '7/3/2019', 4212.00, 0, 0, 0, 0 ],
[ '8/3/2019', 4214.00, 0, 1, 0, 0 ]],
columns=['date','price', 'long_entry', 'long_exit',
'short_entry', 'short_exit'])
df.date = pd.to_datetime(df.date)
Следующим шагом является генерация df2
содержащие только строки для начала и конца длинных записей (на самом деле понадобятся только столбцы дата и цена , но для иллюстрации я включил также long_entry и long_exit :
df2 = df.query('long_entry > 0 or long_exit > 0').iloc[:,0:4]; df2
Результат (для моих данных):
date price long_entry long_exit
2 2019-02-26 4145.67 1 0
5 2019-01-03 4210.12 0 1
10 2019-06-03 4210.00 1 0
12 2019-08-03 4214.00 0 1
Затем мы должны определить функцию, которая будет применена в ближайшее время:
def fn(src):
return pd.Series([src.iloc[0, 0], src.iloc[1, 1] - src.iloc[0, 1]])
Следующий шаг - применить вышеуказанную функцию к последовательным парам строк (вход и выход), задать имена столбцов и изменить столбец date на индекс:
lProf = df2.groupby(np.arange( len(df2.index)) // 2).apply(fn)
lProf.columns = ['date', 'pnl']
lProf.set_index('date', inplace=True)
Результат:
pnl
date
2019-02-26 64.45
2019-06-03 4.00
Пока у нас есть данные для вставки из длинных записей. Теперь пришло время создать похожий DataFrame для коротких записей,применяя ту же функцию, что и раньше:
df2 = df.query('short_entry > 0 or short_exit > 0').iloc[:,[0, 1, 4, 5]]
sProf = df2.groupby(np.arange( len(df2.index)) // 2).apply(fn)
sProf.columns = ['date', 'pnl']
sProf.set_index('date', inplace=True)
Но на этот раз мы должны изменить знакисходные значения:
sProf = -sProf
Результат:
pnl
date
2019-04-03 -119.11
Прежде чем мы добавим результаты в основной DataFrame, мы должны установить столбец date в качестве индекса:
df.set_index('date', inplace=True)
И теперь мы добавляем результаты long записей:
df['pnl'] = lProf
Это создало новый столбец, так что теперь, чтобы добавить результаты коротких записей, мы должны сделать update :
df.update(sProf)
Если вы хотите, чтобы date вернулось как обычностолбец, запустить:
df.reset_index(inplace=True)