Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kraken: Action Types in CSV Exports #100

Merged
merged 26 commits into from
Mar 19, 2022
Merged
Changes from 1 commit
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
ad3563d
updated Kraken mapping
Griffsano Jan 2, 2022
75e027d
different way of handling Kraken exports
Griffsano Jan 2, 2022
7cef9ac
removed trailing whitespace
Griffsano Jan 2, 2022
d49bd63
try inverse pair if Kraken pair is invalid
Griffsano Jan 3, 2022
fbf0609
reduce number of margin trading warnings
Griffsano Jan 3, 2022
9f377f3
allow future timestamp for virtual sells
Griffsano Jan 3, 2022
c71d9e1
address review comments - WIP
Griffsano Jan 4, 2022
e9d809d
reworked Kraken API warnings/errors
Griffsano Jan 5, 2022
1b78544
throw error for margin trades
Griffsano Jan 6, 2022
883c3e5
updated handling of Kraken deposits/withdrawals
Griffsano Jan 15, 2022
4722b63
updated Kraken API handling of latest trade prices
Griffsano Jan 16, 2022
5870134
updated type annotation
Griffsano Jan 23, 2022
c03b90f
added Optional[str] to str conversion
Griffsano Jan 23, 2022
31cba9a
stake rewarded coins
Griffsano Jan 26, 2022
1870cd1
UPDATE Specify error message when refid parameters doe not match
provinzio Feb 5, 2022
ca11a5d
UPDATE autoformat
provinzio Feb 5, 2022
adb45e4
UPDATE deposit logic, ADD comment for staking rewards
Griffsano Feb 6, 2022
e250176
REFACTOR store invalid API Kraken pairs in list and don't try them again
Griffsano Feb 19, 2022
f002f02
REFACTOR handling of Kraken deposits/withdrawals
Griffsano Feb 19, 2022
2385dfe
ADD create_operation and append_created_operation
Griffsano Feb 20, 2022
f461f5f
REFACTOR handling of deposits/withdrawals based on stored operation c…
Griffsano Feb 20, 2022
99baef5
REFACTOR create_operation, append_operation
Griffsano Feb 20, 2022
09817ed
AUTOFORMAT book
provinzio Mar 19, 2022
7a05a50
FIX typo
provinzio Mar 19, 2022
20d521d
CHANGE raise TypeError instead of RuntimeError for wrong type
provinzio Mar 19, 2022
6ccfdc0
UPDATE shorten comment to fit into line
provinzio Mar 19, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 69 additions & 60 deletions src/book.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import decimal
import logging
import re
from collections import defaultdict
from pathlib import Path
from typing import Any, Optional

Expand All @@ -32,6 +33,12 @@


class Book:
# Need to track state of duplicate deposit/withdrawal entries
# All deposits/withdrawals are held back until they occur a second time
# Initialize non-existing fields with None once they're called
kraken_held_ops: defaultdict[str, defaultdict[str, Any]] = \
defaultdict(lambda: defaultdict(lambda: None))

def __init__(self, price_data: PriceData) -> None:
self.price_data = price_data

Expand Down Expand Up @@ -458,10 +465,6 @@ def _read_kraken_ledgers(self, file_path: Path) -> None:
"withdrawal": "Withdrawal",
}

# Need to track state of duplicate deposit/withdrawal entries
# All deposits/withdrawals are held back until they occur a second time
held_operations: list[dict[str, Any]] = []

with open(file_path, encoding="utf8") as f:
reader = csv.reader(f)

Expand Down Expand Up @@ -574,73 +577,79 @@ def _read_kraken_ledgers(self, file_path: Path) -> None:
# in the public trade history and are skipped.
# For staking / unstaking / staking reward actions, deposits /
# withdrawals only occur once and will be ignored.
# The "appended" flag stores if an operation for a given refid has
# already been appended to the operations list:
# == None: Initial value, this is the first occurence
# == False: No operation has been appended, this is the second occurene
Griffsano marked this conversation as resolved.
Show resolved Hide resolved
# == True: Operation has already been appended, this should not happen
if operation in ["Deposit", "Withdrawal"]:
# search for refid in refids list
refid_idxs = [
idx
for idx, op in enumerate(held_operations)
if op["refid"] == refid
]
# refid should not exist more than once in list
if len(refid_idxs) > 1:
log.error(
f"{file_path} row {row}: More than two entries with refid "
f"{refid} should not exist ({operation}). "
"Please create an Issue or PR."
)
raise RuntimeError
# if refid already exists, assert that data of operations agree
if refid_idxs:
idx = refid_idxs[0]
# If this is the first occurence, set the "appended" flag to false
# and don't append the operation to the list. Instead, store the
# data for verifying or appending it later.
if self.kraken_held_ops[refid]["appended"] is None:
append_operation = False
self.kraken_held_ops[refid]["appended"] = False
self.kraken_held_ops[refid]["operation"] = operation
Griffsano marked this conversation as resolved.
Show resolved Hide resolved
self.kraken_held_ops[refid]["utc_time"] = utc_time
self.kraken_held_ops[refid]["platform"] = platform
self.kraken_held_ops[refid]["change"] = change
self.kraken_held_ops[refid]["coin"] = coin
self.kraken_held_ops[refid]["row"] = row
self.kraken_held_ops[refid]["file_path"] = file_path
self.kraken_held_ops[refid]["fee"] = fee
# If this is the second occurence, append a new operation, set the
# "appended" flag to True and assert that the data of this operation
# agrees with the data of the first occurence.
elif self.kraken_held_ops[refid]["appended"] is False:
append_operation = True
self.kraken_held_ops[refid]["appended"] = True
try:
assert (
operation == held_operations[idx]["operation"]
operation == self.kraken_held_ops[refid]["operation"]
), "operation"
assert change == held_operations[idx]["change"], "change"
assert coin == held_operations[idx]["coin"], "coin"
assert (
change == self.kraken_held_ops[refid]["change"]
), "change"
assert coin == self.kraken_held_ops[refid]["coin"], "coin"
except AssertionError as e:
log.error(
f"{file_path} row {row}: Parameters for refid {refid} "
f"({operation}) do not agree: {e} "
f"({operation}) do not agree: {e}. "
"Please create an Issue or PR."
)
raise RuntimeError
# add all entries to refid list and held operations list
held_operations.append(
{
"refid": refid,
"operation": operation,
"utc_time": utc_time,
"platform": platform,
"change": change,
"coin": coin,
"row": row,
"file_path": file_path,
"fee": fee,
}
)
# If an operation with the same refid has been already appended,
# this is the third occurence. Throw an error if this happens.
elif self.kraken_held_ops[refid]["appended"] is True:
log.error(
f"{file_path} row {row}: More than two entries with refid "
f"{refid} should not exist ({operation}). "
"Please create an Issue or PR."
)
raise RuntimeError
# This should never happen
else:
log.error(
f"{file_path} row {row}: Unknown value for appended "
f"operation flag {self.kraken_held_ops[refid]['appended']}."
"Please create an Issue or PR."
)
raise RuntimeError

if operation == "Deposit":
# append only the second deposit to the operations list
append_operation = len(refid_idxs) == 1
elif operation == "Withdrawal":
# Append the first withdrawal to the operations list as soon
# as the second withdrawal occurs. Therefore, for the second
# withdrawal, overwrite the variables with the data of the first
# withdrawal and append this to the operations list.
if refid_idxs:
append_operation = True
# required for type annotation: convert Optional[str] to str
operation = str(held_operations[idx]["operation"])
utc_time = held_operations[idx]["utc_time"]
platform = held_operations[idx]["platform"]
change = held_operations[idx]["change"]
coin = held_operations[idx]["coin"]
row = held_operations[idx]["row"]
file_path = held_operations[idx]["file_path"]
fee = held_operations[idx]["fee"]
else:
append_operation = False
# For deposits, this is all we need to do.
# For withdrawals, we need to append the first withdrawal as soon as
# the second withdrawal occurs. Therefore, overwrite the variables
# with the data of the first withdrawal and append it.
if append_operation and operation == "Withdrawal":
# required for type annotation: convert Optional[str] to str
operation = str(self.kraken_held_ops[refid]["operation"])
utc_time = self.kraken_held_ops[refid]["utc_time"]
platform = self.kraken_held_ops[refid]["platform"]
change = self.kraken_held_ops[refid]["change"]
coin = self.kraken_held_ops[refid]["coin"]
row = self.kraken_held_ops[refid]["row"]
file_path = self.kraken_held_ops[refid]["file_path"]
fee = self.kraken_held_ops[refid]["fee"]
Griffsano marked this conversation as resolved.
Show resolved Hide resolved

if append_operation:
self.append_operation(
Expand Down