-
Notifications
You must be signed in to change notification settings - Fork 8
/
analyzer.py
executable file
·143 lines (121 loc) · 5.07 KB
/
analyzer.py
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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#!/usr/bin/env python
import argparse
import logging
import os.path
import sys
import time
from bitshares_tradehistory_analyzer.ccgains_helper import BagQueue, TradeHistory
logger = logging.getLogger('ccgains')
logger.setLevel(logging.DEBUG)
# This is my highest logger, don't propagate to root logger:
logger.propagate = 0
# Reset logger in case any handlers were already added:
for handler in logger.handlers[::-1]:
handler.close()
logger.removeHandler(handler)
# Create file handler which logs even debug messages
fname = 'ccgains_%s.log' % time.strftime("%Y%m%d-%H%M%S")
fh = logging.FileHandler(fname, mode='w')
fh.setLevel(logging.DEBUG)
# Create console handler for debugging:
ch = logging.StreamHandler(stream=sys.stdout)
ch.setLevel(logging.DEBUG)
# Create formatters and add them to the handlers
fhformatter = logging.Formatter('%(asctime)s %(levelname)-8s - %(module)13s -> %(funcName)-13s: ' '%(message)s')
chformatter = logging.Formatter('%(levelname)-8s: %(message)s')
# fh.setFormatter(fhformatter)
fh.setFormatter(chformatter)
ch.setFormatter(chformatter)
# Add the handlers to the logger
logger.addHandler(fh)
logger.addHandler(ch)
def log_bags(bags):
logger.info("State of bags: \n%s\n", ' ' + '\n '.join(str(bags).split('\n')))
def main():
parser = argparse.ArgumentParser(
description='Analyze bitshares trading history using FIFO/LIFO/LPFO accounting methods',
epilog='Report bugs to: https://github.com/bitfag/bitshares-tradehistory-analyzer/issues',
)
parser.add_argument('-d', '--debug', action='store_true', help='enable debug output'),
parser.add_argument('-c', '--config', default='./config.yml', help='specify custom path for config file')
parser.add_argument('-m', '--mode', default='LPFO', help='inventory accounting mode')
parser.add_argument('-p', '--precision', type=int, help='custom precision for BASE currency columns')
parser.add_argument('-y', '--year', default=None, type=int, help='Generate report for specified year only')
parser.add_argument(
'--short-only', action='store_true', default=False, help='generate only short report (skip detailed report)'
)
parser.add_argument('base_currency', help='BASE currency like USD/CNY/RUDEX.BTC')
parser.add_argument('account', help='bitshares account name')
args = parser.parse_args()
bf = BagQueue(args.base_currency, None, mode=args.mode)
th = TradeHistory()
th.append_csv('transfers-{}.csv'.format(args.account))
th.append_csv('trades-{}.csv'.format(args.account))
status_filename = 'status-{}-{}-{}.json'.format(args.account, args.mode, args.base_currency)
if os.path.isfile(status_filename):
bf.load(status_filename)
last_trade = 0
while last_trade < len(th.tlist) and th[last_trade].dtime <= bf._last_date:
last_trade += 1
if last_trade > 0:
logger.info("continuing with trade #%i" % (last_trade + 1))
# Now, the calculation. This goes through your imported list of trades:
for i, trade in enumerate(th.tlist[last_trade:]):
# Most of this is just the log output to the console and to the
# file 'ccgains_<date-time>.log'
# (check out this file for all gory calculation details!):
logger.info('TRADE #%i', i + last_trade + 1)
logger.info(trade)
# Don't try to process base currency transfers to avoid error from ccgains
if trade.kind == 'Deposit' and trade.buycur == args.base_currency:
continue
elif trade.kind == 'Withdrawal' and trade.sellcur == args.base_currency:
continue
elif trade.kind == 'Withdrawal':
# TODO: don't process withdrawals for now
continue
# This is the important part:
bf.process_trade(trade)
# more logging:
log_bags(bf)
logger.info("Totals: %s", str(bf.totals))
logger.info("Gains (in %s): %s\n" % (bf.currency, str(bf.profit)))
bf.save(status_filename)
my_column_names = [
'Type',
'Amount spent',
u'Currency',
'Purchase date',
'Sell date',
u'Exchange',
u'Short term',
'Purchase cost',
'Proceeds',
'Profit',
]
formatters = {}
if args.precision:
def btc_formatter(value):
return '{:.{prec}f}'.format(value, prec=args.precision)
formatters = {'Purchase cost': btc_formatter, 'Proceeds': btc_formatter, 'Profit': btc_formatter}
bf.report.export_report_to_pdf(
'Report-{}-{}-{}.pdf'.format(args.account, args.mode, args.year),
date_precision='D',
combine=True,
custom_column_names=my_column_names,
custom_formatters=formatters,
year=args.year,
locale="en_US",
)
if not args.short_only:
bf.report.export_extended_report_to_pdf(
'Details-{}-{}-{}.pdf'.format(args.account, args.mode, args.year),
date_precision='S',
combine=False,
font_size=10,
year=args.year,
locale="en_US",
)
# run the main() function above:
if __name__ == "__main__":
main()