ich brauche euren Rat.
Mit einem „kleinen Projekt“ habe ich mir – so wie es aussieht - zu viel zugemutet. Was meint ihr, kann ich das als „Auftrag“ von einem Python-Programmierer machen lassen?
Ich glaube nicht (mehr) – nach meinen Erfahrungen die ich bis jetzt mit Python gesammelt habe - dass ich es selber mit Hilfestellung in den nächsten ca. 7 Tagen fertig bekomme. Das wäre aber notwendig, da mir das Finanzamt im Nacken sitzt.
Ich selbst bin ganz am Anfang von Python und auch in Buchhaltung eher Amateur. Das kann die Sache doch recht verzwickt (zeitaufwendig) machen!
Versuch einer Beschreibung der Aufgabe:
Es geht um FIFO (First In – First Out) Buchhaltung (Gewinn/Verlustermittlung (G/V)) an Hand von csv Daten. Ich brauche dieses Vorgehen für meine Einkommensteuererklärung.
Wenn in den Datensätzen (daten.csv) ein Datensatz mit „sell“ (Verkauf) auftritt, soll dieser mit dem ältesten „buy“ (Kauf) Datensatz verrechnet werden.
Beispiel (Amount BTC hat acht Nachkommastellen, Rate EUR hat zwei):
Datei: daten.csv
Code: Alles auswählen
DateTime,Typ,Amount (BTC),Rate (EUR)
2017-01-08 11:43:00,buy,0.10000001,200.11
2017-01-08 11:43:00,buy,1.00000002,210.55
2017-01-10 16:11:44,sell,0.10000002,290.44
2017-01-11 18:43:00,buy,0.30000003,300.88
2017-01-12 18:55:00,buy,0.40000004,311.22
2017-01-14 22:22:11,sell,0.90000000,444.88
2018-02-15 09:22:55,sell,0.80000008,555.77
Rate = der Kurs in EUR (BTC/EUR, ein Bitcoin entspricht x EUR)
buy = Kauf
sell = Verkauf
So wie ich die Fifo Buchhaltung verstanden habe gibt es quasi zwei Teilschritte.
1. Teilschritt Amount BTC, Ermittlung der Anzahl/Menge bei der Verrechnung von Verkauf und Kauf Datensätzen. D.h. wenn die Anzahl/Amount von Verkauf und Kauf Datensätzen unterschiedlich ist und man z.B. gezwungen wird für einen Verkauf zwei(!) unterschiedliche Kauf Datensätze heranzuziehen:
Datensatz: (1. Verkauf) 2017-01-10 16:11:44,sell,0.10000002,290.44
Datensatz: (1. Kauf) 2017-01-08 11:43:00,buy,0.10000001,200.11
1.1 Berechnung Amount: (1. Kauf - 1. Verkauf) 0.10000001 - 0.10000002 = - 0.00000001 BTC (Rest 1. Verkauf)
Der 1. Verkauf hat hier einen größeren Amount als der Kauf, so muss für den Rest des 1. Verkauf (-0.00000001) der nächste (2. Kauf) herangezogen werden.
Datensatz: (2. Kauf) 2017-01-08 11:43:00,buy,1.00000002,210.55
Datensatz: (Rest 1. Verkauf) 2017-01-10 16:11:44,sell,0.00000001,290.44
1.2 Berechnung Amount: (2. Kauf - Rest 1. Verkauf) 1.00000002 - 0.00000001 = 1.00000001 BTC (Rest 2. Kauf)
Nun hat der BTC Amount vom 2. Kauf einen Rest und muss mit dem nächsten 2.Verkauf BTC Amount verrechnet werden. Usw.
Bei den 7 Beispieldatensätzen soll am Ende für BTC Amount 0.00000000 herauskommen.
2. Teilschritt EUR, Kursdifferenz von Kauf/Verkauf, um den G/V in EUR von den sell/buy Datensatzpaaren zu berechnen.
Datensatz: (1. Verkauf) 2017-01-10 16:11:44,sell,0.10000002,290.44
Datensatz: (1. Kauf) 2017-01-08 11:43:00,buy,0.10000001,200.11
2.1 Berechnung EUR: (1. Kauf Amount * (1. Verkauf Rate - 1. Kauf Rate)) 0.10000001 * (290.44-200.11) = 9.03300181 EUR (G/V)
Der 1. Kauf Amount musste zur Berechnung genommen werden, weil er kleiner als der Verkauf Amount ist und ein Rest von - 0.00000001 BTC (Rest 1. Verkauf) übrig bleibt.
Dann käme der (Rest 1. Verkauf), der mit dem (2. Kauf) verrechnet werden muss.
Datensatz: (Rest 1. Verkauf) 2017-01-10 16:11:44,sell,0.00000001,290.44
Datensatz: (2. Kauf) 2017-01-08 11:43:00,buy,1.00000002,210.55
2.2 Berechnung EUR: (Rest 1. Verkauf Amount * (1. Verkauf Rate - 2. Kauf Rate)) 0.00000001 * (290.44-210.55) = 71.90100000 EUR (G/V)
Usw.
Bis hier wären die beiden ersten buy/sell Datensätze komplett bearbeitet.
Datensatz: (1. Verkauf) 2017-01-10 16:11:44,sell,0.10000002,290.44
Datensatz: (1. Kauf) 2017-01-08 11:43:00,buy,0.10000001,200.11
und es würde weitergehen mit 1. Teilschritt Amount BTC bei:
Datensatz: (Rest 2. Kauf) 2017-01-08 11:43:00,buy,1.00000001,210.55
Wäre das ausreichend genug beschrieben? Kann man daran den Aufwand/Kosten abschätzen wenn ich das von einen Programmierer machen lassen will?
Zum Thema FIFO habe ich die letzten Monate das Internet durchforstet und verschiedene Programme, Onlinedienste und Scripte ausprobiert. Für mich habe ich nichts passendes gefunden, dass sich auf die Kernfunktion von FIFO beschränkt. Überall werden noch „Extras“ wie verschiedene Datenformate, Währungsumrechnung und diverse Gebühren miteinbezogen. Und viele sind beta und funktionieren nur eingeschränkt, bzw. sind auch mit erheblichem Lernaufwand verbunden, der dann doch nicht zum gewünschten Ziel führte. Oder bei den Onlinediensten ist das Thema Datenschutz nicht genug berücksichtigt. Die Programme sind nicht Open Source usw.
U.a habe ich mich auch mit ledger cli (hledger, beancount), GnuCash, beschäftigt.
Meine idealistischen Hintergedanken bei der ganzen Sache war die Idee, eine (simple) Open Source Lösung für Fifo via „Gitlab“ etc. auch anderen zur Verfügung zu stellen. Für Leute die z.B. mit Kryptowährungen werkeln aber auch für andere Daten die eine Fifo Berechnung brauchen und sei es, wenn jemand nur einen Vergleich für seine eigenen Methoden braucht. Simpel, offen (Open Source) und offline verwendbar.
Meine Ansätze in Python:
Bisher habe ich mit Python die csv Daten in Listen eingelesen, auf die Elemente der (verschachtelten) Listen zugegriffen und versucht erste Berechnungen zu machen.
Das ist mein zweiter Python-Versuch, hier war die Priorität die ersten Datensätze (Listen) zu erreichen.
Code: Alles auswählen
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import csv
""" daten.csv
row[0], row[1], row[2], row[3],
DateTime, Typ, Amount, Rate
2017-01-08 11:43:00,buy,0.10000001,200.11
2017-01-08 11:43:00,buy,1.00000002,210.55
2017-01-10 16:11:44,sell,0.10000002,290.44
2017-01-11 18:43:00,buy,0.30000003,300.88
2017-01-12 18:55:00,buy,0.40000004,311.22
2017-01-14 22:22:11,sell,0.90000000,444.88
2018-02-15 09:22:55,sell,0.80000008,555.77
"""
sID = 0 # Zähler für "if" sell Durchläufe
bID = 0 # Zähler für "elif" buy Durchläufe
h_array = [] # history import alle Listen
b_array = [] # buy Listen
s_array = [] # sell Listen
amt_diff = 0 # =SellAmt 0.10000002 -BuyAmt 0.10000001 =0.00000001
rate_diff = 0 # = rate_s - rate_b
for_id =0 # Zähler row[] "for" Durchläufe
with open('daten.csv') as csvDataFile:
csvList = csv.reader(csvDataFile)
for row in csvList:
for_id = for_id+1
h_array.append(row) # alle Zeilen (Listen) in Array speichern, "anhängen"
if row[1] == "sell": # Sell Datensätze ermitteln
sID = sID +1 # ID für sell listen
s_list = row # sell Zeilen in Liste
s_array.append(s_list) # Sell Listen in Array
elif row[1] == "buy": # Buy Datensätze ermitteln
bID = bID +1
b_list = row # analog zu sell
b_array.append(b_list)
# Berechnung der ersten Sell und Buy (BTC) AMOUNT Differenz
amt_s = s_array[0][2] # Erste Liste mit Sell Amount
amt_b = b_array[0][2] # Erste Liste mit Buy Amount
amt_s = float(amt_s) # Umwandlunf in Float (Sell Amount)
amt_b = float(amt_b)
amt_diff = amt_s - amt_b # Erste Differenz von Sell+Buy Amount
print("1. Berechnung\n",
" 1. Datensatz: 2017-01-08 11:43:00, buy, 0.10000001, 200.11\n",
" 3. Datensatz: 2017-01-10 16:11:44, sell, 0.10000002, 290.44")
print("AMOUNT:","SellAmt",amt_s,"-","BuyAmt",amt_b,"=",
("%.8f" % amt_diff),"(Sell/Buy Diff=0.00000001)") # First amt_diff = 0.00000001
# Berechnung der ersten Sell und Buy (EUR) RATE Differenz
rate_s = s_array[0][3] # Erster Sell Rate
rate_b = b_array[0][3] # Erster Buy Rate
rate_s = float(rate_s)
rate_b = float(rate_b)
rate_diff = rate_s - rate_b # Berechnung von Kurs Diff. Sell/Buy (für P/L)
print("RATE: Sell Rate",rate_s,"-","Buy Rate",rate_b,"=","Diff:",("%.2f" % rate_diff),"(90.33)")
# Berechnung EUR: (1. Datensatz Buy Amt * (Sell Rate - Buy Rate) 0.10000001 * (290.44-200.11)
# = 9.03300181 EUR (G/V))
eur_pl = amt_b * (rate_s - rate_b)
print("€ P/L: Buy Amt",("%.8f" % amt_b),"* (Sell Rate",rate_s," - Buy Rate",rate_b,")=",
("%.8f" % eur_pl))
Code: Alles auswählen
1. Berechnung
1. Datensatz: 2017-01-08 11:43:00, buy, 0.10000001, 200.11
3. Datensatz: 2017-01-10 16:11:44, sell, 0.10000002, 290.44
AMOUNT: SellAmt 0.10000002 - BuyAmt 0.10000001 = 0.00000001 (Sell/Buy Diff=0.00000001)
RATE: Sell Rate 290.44 - Buy Rate 200.11 = Diff: 90.33 (90.33)
€ P/L: Buy Amt 0.10000001 * (Sell Rate 290.44 - Buy Rate 200.11 )= 9.03300090
Bei meinem ersten Python-Versuch, war die Priorität alle Datensätze (Listen) zu durchlaufen. Die Berechnungen stimmen noch gar nicht.
Code: Alles auswählen
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import csv
""" daten.csv
row[0], row[1], row[2], row[3],
DateTime, Typ, Amount, Rate
2017-01-08 11:43:00,buy,0.10000001,200.11
2017-01-08 11:43:00,buy,1.00000002,210.55
2017-01-10 16:11:44,sell,0.10000002,290.44
2017-01-11 18:43:00,buy,0.30000003,300.88
2017-01-12 18:55:00,buy,0.40000004,311.22
2017-01-14 22:22:11,sell,0.90000000,444.88
2018-02-15 09:22:55,sell,0.80000008,555.77
"""
sID = 0
bID = 0
h_array = [] # history
b_array = [] # buy
s_array = [] # sell
s1_amt = 0
b1_amt = 0
amt_diff = 0
rate_diff = 0
rate_sb = 0
for_id =0 # amount (row[2])
with open('daten.csv') as csvDataFile:
csvList = csv.reader(csvDataFile)
for row in csvList:
for_id = for_id+1
h_array.append(row) # alle Zeilen in Array speichern, "anhängen"
if row[1] == "sell":
sID = sID +1 # ID für sell listen
s_list = row # sell Zeilen in Liste
s_array.append(s_list) # Sell Listen in Array
s1_amt = s_list[2] # 1 Amount (nur row, weil schon in[array])
s1_amt = float(s1_amt) # Amount als float
diff_s_amt = b1_amt*s1_amt
print(sID,"ID","SLD-Liste:",s_list)
print(" --> Sell Amount (s1_amt):",("%.8f" % s1_amt)) # ("%.8f" % var) bedeutet Nachkommastellen
print(" Buy/Sell Amount Diff. (b1_amt - s1_amt):",("%.8f" % b1_amt),"-",
("%.8f" % s1_amt),"=",("%.8f" % diff_s_amt))
elif row[1] == "buy":
bID = bID +1
b_list = row
b_array.append(b_list)
b1_amt = b_list[2] # 1 Amount aus b_list[row]
b1_amt = float(b1_amt)
diff_b_amt = b1_amt*s1_amt
print(bID,"ID","BUY-Liste:",b_list)
print(" --> Buy Amount (b1_amt):",b1_amt)
print(" Buy/Sell Amount Diff. (b1_amt - s1_amt):",("%.8f" % b1_amt),"-",
("%.8f" % s1_amt),"=",("%.8f" % diff_b_amt))
print("---------------------------------",for_id,".","Durchlauf--------------------------------------")
Code: Alles auswählen
1 ID BUY-Liste: ['2017-01-08 11:43:00', 'buy', '0.10000001', '200.11']
--> Buy Amount (b1_amt): 0.10000001
Buy/Sell Amount Diff. (b1_amt - s1_amt): 0.10000001 - 0.00000000 = 0.00000000
--------------------------------- 1 . Durchlauf--------------------------------------
2 ID BUY-Liste: ['2017-01-08 11:43:00', 'buy', '1.00000002', '210.55']
--> Buy Amount (b1_amt): 1.00000002
Buy/Sell Amount Diff. (b1_amt - s1_amt): 1.00000002 - 0.00000000 = 0.00000000
--------------------------------- 2 . Durchlauf--------------------------------------
1 ID SLD-Liste: ['2017-01-10 16:11:44', 'sell', '0.10000002', '290.44']
--> Sell Amount (s1_amt): 0.10000002
Buy/Sell Amount Diff. (b1_amt - s1_amt): 1.00000002 - 0.10000002 = 0.10000002
--------------------------------- 3 . Durchlauf--------------------------------------
3 ID BUY-Liste: ['2017-01-11 18:43:00', 'buy', '0.30000003', '300.88']
--> Buy Amount (b1_amt): 0.30000003
Buy/Sell Amount Diff. (b1_amt - s1_amt): 0.30000003 - 0.10000002 = 0.03000001
--------------------------------- 4 . Durchlauf--------------------------------------
4 ID BUY-Liste: ['2017-01-12 18:55:00', 'buy', '0.40000004', '311.22']
--> Buy Amount (b1_amt): 0.40000004
Buy/Sell Amount Diff. (b1_amt - s1_amt): 0.40000004 - 0.10000002 = 0.04000001
--------------------------------- 5 . Durchlauf--------------------------------------
2 ID SLD-Liste: ['2017-01-14 22:22:11', 'sell', '0.90000000', '444.88']
--> Sell Amount (s1_amt): 0.90000000
Buy/Sell Amount Diff. (b1_amt - s1_amt): 0.40000004 - 0.90000000 = 0.36000004
--------------------------------- 6 . Durchlauf--------------------------------------
3 ID SLD-Liste: ['2018-02-15 09:22:55', 'sell', '0.80000008', '555.77']
--> Sell Amount (s1_amt): 0.80000008
Buy/Sell Amount Diff. (b1_amt - s1_amt): 0.40000004 - 0.80000008 = 0.32000006
--------------------------------- 7 . Durchlauf--------------------------------------
Eure konstruktiven Vorschläge sind sehr willkommen.
Fragen wie: „warum nimmst du keine Dictionaries oder NumPy?“ Kann ich bei meinem Kenntnislevel nicht beantworten, weil ich diese Methoden nicht gut genug kenne.
Und nun läuft mir ja die Zeit davon und meine Kapazitätsgrenzen tauchen am Horizont auf.
Danke.
PS: Wenn es möglich ist meine Idee als Auftrag zu packen, dann wäre das Offtopic Forum dafür richtig?