Почему я получаю некорректный расчет по методу FIFO в Python?

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

Я пытаюсь написать код для расчета себестоимости проданной валюты методом FIFO. Брокерский отчет разбит на две таблицы со сделками покупок и продаж.

    Номер       Вид_сделки  Наименование Цена/ед.   Количество  Сумма   Валюта  Дата
0   215444826   Покупка     USDRUB_TOM   61.2000    150         9180.00 RUB     10.01.2020
1   215611371   Покупка     USDRUB_TOM   61.3325    1           61.33   RUB     13.01.2020
2   215762332   Покупка     USDRUB_TOM   61.0875    100         6108.75 RUB     14.01.2020
3   215922580   Покупка     USDRUB_TOM   61.3900    70          4297.30 RUB     15.01.2020
4   215926516   Покупка     USDRUB_TOM   61.3275    1           61.33   RUB     15.01.2020
5   218340663   Покупка     USDRUB_TOM   63.2175    100         6321.75 RUB     05.02.2020
6   218514960   Покупка     USDRUB_TOM   62.8525    50          3142.63 RUB     06.02.2020
7   218555601   Покупка     USDRUB_TOM   62.7200    75          4704.00 RUB     06.02.2020
8   218578024   Покупка     USDRUB_TOM   62.6625    75          4699.69 RUB     06.02.2020
9   219928930   Покупка     USDRUB_TOM   63.2950    100         6329.50 RUB     18.02.2020


    Номер       Вид_сделки  Наименование Цена/ед. Количество  Сумма     Валюта  Дата        Sell_cnt
1   215133588   Продажа     USDRUB_TOM   61.7225  1000        61722.50  RUB     09.01.2020  1000
2   219990323   Продажа     USDRUB_TOD   63.7625  3           191.2     RUB     18.02.2020  3
3   229240134   Продажа     USDRUB_TOD   73.8525  9           664.6     RUB     10.04.2020  9
4   229442079   Продажа     USDRUB_TOD   73.5475  149         10958.58  RUB     13.04.2020  149
5   230692120   Продажа     USDRUB_TOD   74.7800  114         8524.92   RUB     20.04.2020  114

Для расчетов написал следующий код:

for i, row_s in df_sell.iterrows():
Buy_cost = 0
while row_s['FIFO_sell'] > 0:
    for j, row_b in df_buy.iterrows():
        if row_s['FIFO_sell'] > row_b['FIFO_buy']:
            Buy_cost = Buy_cost + row_b['FIFO_buy'] * row_b['Цена/ед.']
            row_s['FIFO_sell'] = row_s['FIFO_sell'] - row_b['FIFO_buy']
            row_b['FIFO_buy'] = 0

        elif row_s['FIFO_sell'] == row_b['FIFO_buy']:
            Buy_cost = Buy_cost + row_s['FIFO_sell'] * row_b['Цена/ед.']
            row_s['FIFO_sell'] = 0
            row_b['FIFO_buy'] = 0

        else:
            Buy_cost = Buy_cost + row_s['FIFO_sell'] * row_b['Цена/ед.']
            row_b['FIFO_buy'] = row_b['FIFO_buy'] - row_s['FIFO_sell']
            row_s['FIFO_sell'] = 0

    df_sell.at[i, "Себестоимость покупки"] = Buy_cost

Однако код корректно работает только для первой сделки по продаже, далее курс покупки валюты получается заниженным.

    Номер       Вид_сделки  Наименование  Цена/ед.  Количество  Сумма        Валюта Дата        FIFO_sell  Себестоимость_покупки
1   215133588   Продажа     USDRUB_TOM    61.7225   1000        61722.50     RUB    09.01.2020  1000       66271.7775
31  219990323   Продажа     USDRUB_TOD    63.7625   3           191.29       RUB    18.02.2020  3          183.6000
101 229240134   Продажа     USDRUB_TOD    73.8525   9           664.67       RUB    10.04.2020  9          550.8000
123 229442079   Продажа     USDRUB_TOD    73.5475   149         10958.58     RUB    13.04.2020  149        9118.8000
168 230692120   Продажа     USDRUB_TOD    74.7800   114         8524.92      RUB    20.04.2020  114        6976.8000

Кроме того, в глаза бросается, что значения в столбцах FIFO_sell и FIFO_buy остаются неизменными, хотя по задумке, все значения должны быть равны 0.

Использую Python 3.9.16 final, VS Code.

Есть мысли, где допущена ошибка?

Спасибо!

Ответы

▲ 0Принят

Написал следующий код:

i = 0
j = 0
Buy_cost = 0
# листы с индексами датафреймов (от 0 до n)
index_sell = list(df_sell.index)
index_buy = list(df_buy.index)
# цикл ограничен размерами массивов
while i <= max(index_sell) and j <= max(index_buy):
    # в цикле сравниваются 1 сделка по покупке и продаже валюты
    if df_sell.at[i, 'Sell_cnt'] > df_buy.at[j, 'Количество']:
        # количество проданных единиц больше количества купленных
        Buy_cost += df_buy.at[j, 'Количество']*df_buy.at[j, 'Цена за единицу']
        df_sell.at[i, 'Sell_cnt'] -= df_buy.at[j, 'Количество']
        df_buy.at[j, 'Количество'] = 0
        j += 1
    elif df_sell.at[i, 'Sell_cnt'] == df_buy.at[j, 'Количество']:
        # количество проданных единиц равно количеству купленных
        Buy_cost += df_buy.at[j, 'Количество']*df_buy.at[j, 'Цена за единицу']
        df_buy.at[j, 'Количество'] = 0
        df_sell.at[i, "Себестоимость покупки"] = round(Buy_cost, 2)
        Buy_cost = 0
        j += 1
        i += 1
    else:
        # количество проданных единиц меньше количества купленных
        Buy_cost += df_sell.at[i, 'Sell_cnt']*df_buy.at[j, 'Цена за единицу']
        df_buy.at[j, 'Количество'] -= df_sell.at[i, 'Sell_cnt']
        df_sell.at[i, "Себестоимость покупки"] = round(Buy_cost, 2)
        Buy_cost = 0
        i += 1

Если у кого-то будут замечания к коду, буду благодарен за конструктивную критику.