Wpis

PIT z Binance w 5 minut dzięki Pythonowi

Jak szybko i wygodnie obliczyć PIT za pomocą biblioteki nbp_sdk

PIT z Binance w 5 minut dzięki Pythonowi

Wprowadzenie

Każda osoba inwestująca w kryptowaluty ma obowiązek złożenia rocznego zeznania podatkowego (formularz PIT-38) do 30 kwietnia. Ręczne wyliczanie podatku może być uciążliwe, dlatego pokażę Ci, jak szybko i wygodnie obliczyć go za pomocą biblioteki nbp_sdk napisanej w Pythonie na przykładzie giełdy Binance.

Przygotowanie

Na swoim systemie operacyjnym zainstaluj pythona w wersji 3.10 albo wyżej. Jeśli nie wiesz jak to zrobić to zajrzyj na oficjalną stronę pobierania. Po wykonaniu tej czynności powinieneś posiadać domyślny menedżer instalacji pakietów pip , ściągnij i wgraj paczkę nbp_sdk za pomocą polecenia:

1
pip install nbp_sdk

Pobierz swoje sprawozdanie roczne ze strony binance, powinno posiadać następujące nagłówki:

1
"User_ID","UTC_Time","Account","Operation","Coin","Change","Remark"

Zapisz plik w głównym katalogu projektu – możesz nadać mu dowolną nazwę, np. 2024.csv.

Na koniec utwórz plik z rozszerzeniem .py, który będzie Twoim programem, np. app.py.

Piszemy program

W pliku app.py

Dodaj bibliotekę do obsługi csv

1
import csv

Dodaj bibliotekę do zarządzania datami

1
from datetime import datetime

Zaimportuj typ Decimal który jest idealny do liczb które muszą być precyzyjne jak kwoty na wyciągu oraz stałą ROUND_HALF_UP która determinuje zachowanie zaokrąglania liczb, w tym przypadku zaokrąglamy w górę.

1
from decimal import Decimal, ROUND_HALF_UP

Dodaj paczkę do łączenia się z narodowym bankiem polskim w celu pobrania kursu przypadającego na dany dzień

1
from nbp_sdk.client import NBPApiClient, CurrencyType

Następnie zdefiniuj funkcję do zaokrąglania kwot. Liczba typu 3.233 zostanie zaokrąglona do 3.23 natomiast 5.5159 do 5.52

1
2
def rounded_decimal(d: Decimal) -> Decimal:
    return d.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)

Utwórz instancję klienta API NBP

1
api = NBPApiClient() 

Oraz dwie zmienne;

  • expanses czyli koszty, tutaj to kwota konwersji z euro na daną kryptowalutę
  • revenues czyli przychodu, tutaj to kwota konwersji z danej kryptowaluty na euro
1
2
expanses = Decimal(0)
revenues = Decimal(0)

A teraz przechodzimy do mięska czyli obsługi i przeliczania kosztów oraz wydatków z pliku csv

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
with open('2024.csv', newline='') as csvfile:
    reader = csv.DictReader(csvfile)
    for row in reader:
        change = Decimal(row["Change"])
        operation = row['Operation']
        coin = row['Coin']

        # expanses
        if operation == "Binance Convert" and coin == "EUR" and  change < 0:
            print(row)

            date = datetime.strptime(row["UTC_Time"], "%Y-%m-%d %H:%M:%S")
            rate = api.get_currency_rate_from_working_day_before_date(CurrencyType.EUR, date)

            print(f"Koszty przed: {rounded_decimal(expanses)}")
            expanses += change * -1 * rate.average_rate
            print(f"Koszty po dodaniu: {rounded_decimal(expanses)}")

        # revenues
        if operation == "Binance Convert" and coin == "EUR" and  change > 0:
            print(row)

            date = datetime.strptime(row["UTC_Time"], "%Y-%m-%d %H:%M:%S")
            rate = api.get_currency_rate_from_working_day_before_date(CurrencyType.EUR, date)

            print(f"Przychody przed: {rounded_decimal(expanses)}")
            revenues += change * rate.average_rate
            print(f"Przychody po dodaniu: {rounded_decimal(expanses)}")


    print(f"Koszty: {rounded_decimal(expanses)} PLN")
    print(f"Przychody: {rounded_decimal(revenues)} PLN")
  1. Otwieramy plik csv 2024.csv i zapisujemy to jako zmienna kontekstowa csvfile
  2. Wczytujemy plik do biblioteki CSV, do zmiennej reader. reader przechowuje listę wierszy csv w postaci słownika {'Nazwa kolumny': 'wartość'}
  3. Iterujemy po wierszach
  4. Definiujemy 3 zmienne:
    • change kwota transakcji
    • operation typ operacji
    • coin typ waluty. Dla Europejczyków będzie to euro
  5. Typ operacji Binance Convert oznacza przewalutowanie i jeśli coin to EUR to z/na euro. Jeśli change jest wartością ujemną to mówimy o koszcie, jeśli dodatnia to o przychodzie
  6. Średni kurs waluty należy pobrać z dnia roboczego poprzedzającego datę transakcji – na przykład, jeśli transakcja miała miejsce w piątek, obowiązuje kurs z czwartku; jeśli w poniedziałek, to z piątku.
  7. Podliczamy koszty i przychody
  8. Wyświetlamy podsumowanie.

    Całość

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import csv
from datetime import datetime
from decimal import Decimal, ROUND_HALF_UP

from nbp_sdk.client import NBPApiClient, CurrencyType

def rounded_decimal(d: Decimal) -> Decimal:
    return d.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)

api = NBPApiClient() 
expanses = Decimal(0)
revenues = Decimal(0)

with open('2024.csv', newline='') as csvfile:
    reader = csv.DictReader(csvfile)
    for row in reader:
        change = Decimal(row["Change"])
        operation = row['Operation']
        coin = row['Coin']

        # expanses
        if operation == "Binance Convert" and coin == "EUR" and  change < 0:
            print(row)

            date = datetime.strptime(row["UTC_Time"], "%Y-%m-%d %H:%M:%S")
            rate = api.get_currency_rate_from_working_day_before_date(CurrencyType.EUR, date)

            print(f"Koszty przed: {rounded_decimal(expanses)}")
            expanses += change * -1 * rate.average_rate
            print(f"Koszty po dodaniu: {rounded_decimal(expanses)}")

        # revenues
        if operation == "Binance Convert" and coin == "EUR" and  change > 0:
            print(row)

            date = datetime.strptime(row["UTC_Time"], "%Y-%m-%d %H:%M:%S")
            rate = api.get_currency_rate_from_working_day_before_date(CurrencyType.EUR, date)

            print(f"Przychody przed: {rounded_decimal(expanses)}")
            revenues += change * rate.average_rate
            print(f"Przychody po dodaniu: {rounded_decimal(expanses)}")


    print(f"Koszty: {rounded_decimal(expanses)} PLN")
    print(f"Przychody: {rounded_decimal(revenues)} PLN")

Wsparcie

Jeśli artykuł ci się do czegoś przydał to postaw mi kawę ☕. Nie musi być to kawa z Starbucksa, taka biedronkowa też jest ok ;) Każda nawet najmniejsza dotacja to sygnał że to co robię jest dla Ciebie wartościowe.

Ten wpis jest licencjonowany na warunkach CC BY 4.0 przez autora.