Рассчитать результат (профит) сделок

Рейтинг: -1Ответов: 1Опубликовано: 13.01.2023

Есть список с вложенными словарями (сделки) необходимо рассчитать профит от сделок.

Профит должен быть рассчитан в последовательности buy -> sell -> buy -> sell... т.е. моя первая покупка(buy) 17 фьючерсов со средней 6025,41 следующая сделка продажа(sell) этих 17 фьючерсов по средней 6015,53

Цифрами: Профит buy = 17 * (6015(sell) - 6025(buy)) итого убыток = -170. Профит sell = 17 * (6025(buy) - 6015(sell)) итого прибыль = +170.

Поэтому в списке важно сохранить последовательность элементов.

qtyUnits = количество акции
side = направление сделки (sell - продажа, buy - покупка)

Сложность еще в том, что сначала необходимо рассчитать среднюю цену для сделки. Т.е. если обратить внимание на orderno он повторяющийся - это одна заявка, а id разные — это сделки из одной заявки, собственно для этих сделок и надо рассчитать среднюю цену(price) и общее кол-во qtyUnits

{'id': '2006663898136052343', 'orderno': '2006663898136074714', 'symbol': 'ALRS-3.23', 'brokerSymbol': 'MOEX:ALRS-3.23', 'exchange': 'MOEX', 'date': '2022-12-27T12:35:59.0000000Z', 'board': None, 'qtyUnits': 10, 'qtyBatch': 10, 'qty': 10, 'price': 6025.0, 'accruedInt': 0, 'side': 'buy', 'existing': True, 'commission': None} 

{'id': '2006663898136052344', 'orderno': '2006663898136074714', 'symbol': 'ALRS-3.23', 'brokerSymbol': 'MOEX:ALRS-3.23', 'exchange': 'MOEX', 'date': '2022-12-27T12:35:59.0000000Z', 'board': None, 'qtyUnits': 7, 'qtyBatch': 7, 'qty': 7, 'price': 6026.0, 'accruedInt': 0, 'side': 'buy', 'existing': True, 'commission': None} 

{'id': '2006663902431019077', 'orderno': '2006663902431021426', 'symbol': 'ALRS-3.23', 'brokerSymbol': 'MOEX:ALRS-3.23', 'exchange': 'MOEX', 'date': '2022-12-27T17:19:27.0000000Z', 'board': None, 'qtyUnits': 1, 'qtyBatch': 1, 'qty': 1, 'price': 6019.0, 'accruedInt': 0, 'side': 'sell', 'existing': True, 'commission': None} 

{'id': '2006663902431019078', 'orderno': '2006663902431021426', 'symbol': 'ALRS-3.23', 'brokerSymbol': 'MOEX:ALRS-3.23', 'exchange': 'MOEX', 'date': '2022-12-27T17:19:27.0000000Z', 'board': None, 'qtyUnits': 2, 'qtyBatch': 2, 'qty': 2, 'price': 6018.0, 'accruedInt': 0, 'side': 'sell', 'existing': True, 'commission': None} 

{'id': '2006663902431019079', 'orderno': '2006663902431021426', 'symbol': 'ALRS-3.23', 'brokerSymbol': 'MOEX:ALRS-3.23', 'exchange': 'MOEX', 'date': '2022-12-27T17:19:27.0000000Z', 'board': None, 'qtyUnits': 1, 'qtyBatch': 1, 'qty': 1, 'price': 6017.0, 'accruedInt': 0, 'side': 'sell', 'existing': True, 'commission': None} 

{'id': '2006663902431019084', 'orderno': '2006663902431021426', 'symbol': 'ALRS-3.23', 'brokerSymbol': 'MOEX:ALRS-3.23', 'exchange': 'MOEX', 'date': '2022-12-27T17:19:27.0000000Z', 'board': None, 'qtyUnits': 3, 'qtyBatch': 3, 'qty': 3, 'price': 6016.0, 'accruedInt': 0, 'side': 'sell', 'existing': True, 'commission': None} 

{'id': '2006663902431019089', 'orderno': '2006663902431021426', 'symbol': 'ALRS-3.23', 'brokerSymbol': 'MOEX:ALRS-3.23', 'exchange': 'MOEX', 'date': '2022-12-27T17:19:27.0000000Z', 'board': None, 'qtyUnits': 2, 'qtyBatch': 2, 'qty': 2, 'price': 6015.0, 'accruedInt': 0, 'side': 'sell', 'existing': True, 'commission': None} 

{'id': '2006663902431019090', 'orderno': '2006663902431021426', 'symbol': 'ALRS-3.23', 'brokerSymbol': 'MOEX:ALRS-3.23', 'exchange': 'MOEX', 'date': '2022-12-27T17:19:27.0000000Z', 'board': None, 'qtyUnits': 2, 'qtyBatch': 2, 'qty': 2, 'price': 6015.0, 'accruedInt': 0, 'side': 'sell', 'existing': True, 'commission': None} 

{'id': '2006663902431019091', 'orderno': '2006663902431021426', 'symbol': 'ALRS-3.23', 'brokerSymbol': 'MOEX:ALRS-3.23', 'exchange': 'MOEX', 'date': '2022-12-27T17:19:27.0000000Z', 'board': None, 'qtyUnits': 6, 'qtyBatch': 6, 'qty': 6, 'price': 6014.0, 'accruedInt': 0, 'side': 'sell', 'existing': True, 'commission': None} 

{'id': '2006663902431019092', 'orderno': '2006663902431021458', 'symbol': 'ALRS-3.23', 'brokerSymbol': 'MOEX:ALRS-3.23', 'exchange': 'MOEX', 'date': '2022-12-27T17:20:01.0000000Z', 'board': None, 'qtyUnits': 6, 'qtyBatch': 6, 'qty': 6, 'price': 6017.0, 'accruedInt': 0, 'side': 'sell', 'existing': True, 'commission': None} 

{'id': '2006663902431019093', 'orderno': '2006663902431021458', 'symbol': 'ALRS-3.23', 'brokerSymbol': 'MOEX:ALRS-3.23', 'exchange': 'MOEX', 'date': '2022-12-27T17:20:01.0000000Z', 'board': None, 'qtyUnits': 11, 'qtyBatch': 11, 'qty': 11, 'price': 6017.0, 'accruedInt': 0, 'side': 'sell', 'existing': True, 'commission': None} 

{'id': '2006663911020954609', 'orderno': '2006663911020981710', 'symbol': 'ALRS-3.23', 'brokerSymbol': 'MOEX:ALRS-3.23', 'exchange': 'MOEX', 'date': '2022-12-30T14:05:36.0000000Z', 'board': None, 'qtyUnits': 4, 'qtyBatch': 4, 'qty': 4, 'price': 5970.0, 'accruedInt': 0, 'side': 'buy', 'existing': True, 'commission': None} 

{'id': '2006663911020954610', 'orderno': '2006663911020981710', 'symbol': 'ALRS-3.23', 'brokerSymbol': 'MOEX:ALRS-3.23', 'exchange': 'MOEX', 'date': '2022-12-30T14:05:36.0000000Z', 'board': None, 'qtyUnits': 10, 'qtyBatch': 10, 'qty': 10, 'price': 5971.0, 'accruedInt': 0, 'side': 'buy', 'existing': True, 'commission': None}

На текущий момент я сумел вывести нужные мне элементы словаря в другой список, а как дальше...

all_deals = []
  
# deals - это список где все словари
      
date = [d['date'] for d in deals]


for dt in date:
    temp_data = []
        for dl in deals:
            if dt in dl['date']:
                temp_data.append((dl['date'], dl['side'], dl['qty'], dl['price'], dl['commission']))

    if temp_data not in all_deals:
        all_deals.append(temp_data)

for item in all_deals:
    print(item,'\n')

Ответы

▲ 2Принят

Ну вот вам общее количество по ордерам и средняя цена с помощью Pandas. Общий баланс операций я тоже прикинул.

import pandas as pd

data = [
{'id': '2006663898136052343', 'orderno': '2006663898136074714', 'symbol': 'ALRS-3.23', 'brokerSymbol': 'MOEX:ALRS-3.23', 'exchange': 'MOEX', 'date': '2022-12-27T12:35:59.0000000Z', 'board': None, 'qtyUnits': 10, 'qtyBatch': 10, 'qty': 10, 'price': 6025.0, 'accruedInt': 0, 'side': 'buy', 'existing': True, 'commission': None},
{'id': '2006663898136052344', 'orderno': '2006663898136074714', 'symbol': 'ALRS-3.23', 'brokerSymbol': 'MOEX:ALRS-3.23', 'exchange': 'MOEX', 'date': '2022-12-27T12:35:59.0000000Z', 'board': None, 'qtyUnits': 7, 'qtyBatch': 7, 'qty': 7, 'price': 6026.0, 'accruedInt': 0, 'side': 'buy', 'existing': True, 'commission': None},
{'id': '2006663902431019077', 'orderno': '2006663902431021426', 'symbol': 'ALRS-3.23', 'brokerSymbol': 'MOEX:ALRS-3.23', 'exchange': 'MOEX', 'date': '2022-12-27T17:19:27.0000000Z', 'board': None, 'qtyUnits': 1, 'qtyBatch': 1, 'qty': 1, 'price': 6019.0, 'accruedInt': 0, 'side': 'sell', 'existing': True, 'commission': None},
{'id': '2006663902431019078', 'orderno': '2006663902431021426', 'symbol': 'ALRS-3.23', 'brokerSymbol': 'MOEX:ALRS-3.23', 'exchange': 'MOEX', 'date': '2022-12-27T17:19:27.0000000Z', 'board': None, 'qtyUnits': 2, 'qtyBatch': 2, 'qty': 2, 'price': 6018.0, 'accruedInt': 0, 'side': 'sell', 'existing': True, 'commission': None},
{'id': '2006663902431019079', 'orderno': '2006663902431021426', 'symbol': 'ALRS-3.23', 'brokerSymbol': 'MOEX:ALRS-3.23', 'exchange': 'MOEX', 'date': '2022-12-27T17:19:27.0000000Z', 'board': None, 'qtyUnits': 1, 'qtyBatch': 1, 'qty': 1, 'price': 6017.0, 'accruedInt': 0, 'side': 'sell', 'existing': True, 'commission': None},
{'id': '2006663902431019084', 'orderno': '2006663902431021426', 'symbol': 'ALRS-3.23', 'brokerSymbol': 'MOEX:ALRS-3.23', 'exchange': 'MOEX', 'date': '2022-12-27T17:19:27.0000000Z', 'board': None, 'qtyUnits': 3, 'qtyBatch': 3, 'qty': 3, 'price': 6016.0, 'accruedInt': 0, 'side': 'sell', 'existing': True, 'commission': None},
{'id': '2006663902431019089', 'orderno': '2006663902431021426', 'symbol': 'ALRS-3.23', 'brokerSymbol': 'MOEX:ALRS-3.23', 'exchange': 'MOEX', 'date': '2022-12-27T17:19:27.0000000Z', 'board': None, 'qtyUnits': 2, 'qtyBatch': 2, 'qty': 2, 'price': 6015.0, 'accruedInt': 0, 'side': 'sell', 'existing': True, 'commission': None},
{'id': '2006663902431019090', 'orderno': '2006663902431021426', 'symbol': 'ALRS-3.23', 'brokerSymbol': 'MOEX:ALRS-3.23', 'exchange': 'MOEX', 'date': '2022-12-27T17:19:27.0000000Z', 'board': None, 'qtyUnits': 2, 'qtyBatch': 2, 'qty': 2, 'price': 6015.0, 'accruedInt': 0, 'side': 'sell', 'existing': True, 'commission': None},
{'id': '2006663902431019091', 'orderno': '2006663902431021426', 'symbol': 'ALRS-3.23', 'brokerSymbol': 'MOEX:ALRS-3.23', 'exchange': 'MOEX', 'date': '2022-12-27T17:19:27.0000000Z', 'board': None, 'qtyUnits': 6, 'qtyBatch': 6, 'qty': 6, 'price': 6014.0, 'accruedInt': 0, 'side': 'sell', 'existing': True, 'commission': None},
{'id': '2006663902431019092', 'orderno': '2006663902431021458', 'symbol': 'ALRS-3.23', 'brokerSymbol': 'MOEX:ALRS-3.23', 'exchange': 'MOEX', 'date': '2022-12-27T17:20:01.0000000Z', 'board': None, 'qtyUnits': 6, 'qtyBatch': 6, 'qty': 6, 'price': 6017.0, 'accruedInt': 0, 'side': 'sell', 'existing': True, 'commission': None},
{'id': '2006663902431019093', 'orderno': '2006663902431021458', 'symbol': 'ALRS-3.23', 'brokerSymbol': 'MOEX:ALRS-3.23', 'exchange': 'MOEX', 'date': '2022-12-27T17:20:01.0000000Z', 'board': None, 'qtyUnits': 11, 'qtyBatch': 11, 'qty': 11, 'price': 6017.0, 'accruedInt': 0, 'side': 'sell', 'existing': True, 'commission': None},
{'id': '2006663911020954609', 'orderno': '2006663911020981710', 'symbol': 'ALRS-3.23', 'brokerSymbol': 'MOEX:ALRS-3.23', 'exchange': 'MOEX', 'date': '2022-12-30T14:05:36.0000000Z', 'board': None, 'qtyUnits': 4, 'qtyBatch': 4, 'qty': 4, 'price': 5970.0, 'accruedInt': 0, 'side': 'buy', 'existing': True, 'commission': None},
{'id': '2006663911020954610', 'orderno': '2006663911020981710', 'symbol': 'ALRS-3.23', 'brokerSymbol': 'MOEX:ALRS-3.23', 'exchange': 'MOEX', 'date': '2022-12-30T14:05:36.0000000Z', 'board': None, 'qtyUnits': 10, 'qtyBatch': 10, 'qty': 10, 'price': 5971.0, 'accruedInt': 0, 'side': 'buy', 'existing': True, 'commission': None},
]

def calc(x):
    totalUnits = x['qtyUnits'].sum()
    totalPrice = (x['qtyUnits'] * x['price']).sum()
    side = 1 if x['side'].iloc[0] == 'sell' else -1
    return pd.Series({'totalUnits': totalUnits, 'avgPrice': totalPrice/totalUnits, 'side': side})

df = pd.DataFrame(data)
total = df.groupby('orderno').apply(lambda x: calc(x))
print(total)
balance_units = -(total['totalUnits'] * total['side']).sum()
balance_money = (total['avgPrice'] * total['totalUnits'] * total['side']).sum()
print(f'Общий баланс +/- покупок и продаж: {balance_units} акций и {balance_money} денег')
print('Закрытия сделок:')
total['balanceUnits'] = -(total['totalUnits'] * total['side']).cumsum()
total['balancePrice'] = (total['avgPrice'] * total['totalUnits'] * total['side']).cumsum()
print(total.loc[total['balanceUnits'] == 0, 'balancePrice'])

Вывод:

                     totalUnits     avgPrice  side
orderno                                           
2006663898136074714        17.0  6025.411765  -1.0
2006663902431021426        17.0  6015.529412   1.0
2006663902431021458        17.0  6017.000000   1.0
2006663911020981710        14.0  5970.714286  -1.0
Общий баланс +/- покупок и продаж: -3.0 акций и 18531.0 денег
Закрытия сделок:
orderno
2006663902431021426   -168.0
Name: balancePrice, dtype: float64