You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
181 lines
5.4 KiB
181 lines
5.4 KiB
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
# ---------------------------------------------------------------------
|
|
# Copyright (c) 2022 NETCRAFT.CH <src@netcraft.ch>
|
|
#
|
|
# All rights reserved.
|
|
#
|
|
# Redistribution and use in source and binary forms, with or without
|
|
# modification, are permitted provided that the following conditions
|
|
# are met:
|
|
# 1. Redistributions of source code must retain the above copyright
|
|
# notice, this list of conditions and the following disclaimer.
|
|
# 2. Redistributions in binary form must reproduce the above copyright
|
|
# notice, this list of conditions and the following disclaimer in the
|
|
# documentation and/or other materials provided with the distribution.
|
|
# 3. The name of the author may not be used to endorse or promote products
|
|
# derived from this software without specific prior written permission.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
|
# THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
|
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
# --------------------------------------------------------------------------
|
|
|
|
#######################
|
|
# IMPORTS
|
|
#######################
|
|
import csv, sys, getopt
|
|
try:
|
|
import requests
|
|
except:
|
|
print ("python-requests library missing, install with:\nsudo apt-get install python3-requests")
|
|
sys.exit(1)
|
|
|
|
#######################
|
|
# CONSTANTS
|
|
#######################
|
|
linelen = 60
|
|
KRK_TICKER_URL = "https://api.kraken.com/0/public/Ticker"
|
|
|
|
#######################
|
|
# FUNCTIONS
|
|
#######################
|
|
def calc_totals(trades):
|
|
#print trades
|
|
sum_s1 = 0
|
|
sum_s2 = 0
|
|
sum_b1 = 0
|
|
sum_b2 = 0
|
|
global quiet
|
|
for t in trades:
|
|
if not quiet:
|
|
print ("%s %s %s %0.4f %f %0.2f" %(t['time'].split(".")[0], t['pair'], t['type'], float(t['price']), float(t['vol']), float(t['cost'])) )
|
|
if t['type'] == 'sell':
|
|
sum_s1 += float(t['vol'])
|
|
sum_s2 += float(t['cost'])
|
|
elif t['type'] == 'buy':
|
|
sum_b1 += float(t['vol'])
|
|
sum_b2 += float(t['cost'])
|
|
if sum_s1 > 0 and sum_s2 >0:
|
|
avg_s = sum_s2 / sum_s1
|
|
else:
|
|
avg_s = 0
|
|
if sum_b1 > 0 and sum_b2 >0:
|
|
avg_b = sum_b2 / sum_b1
|
|
else:
|
|
avg_b = 0
|
|
|
|
if not quiet: hrule("=")
|
|
print ("*BUY*:\tAmount\t\tVolume\t\tAvg. price")
|
|
print ("\t%f\t%f\t%f" %(sum_b1, sum_b2, avg_b))
|
|
print ("*SELL*:\tAmount\t\tVolume\t\tAvg. price")
|
|
print ("\t%f\t%f\t%f" %(sum_s1, sum_s2, avg_s) )
|
|
hrule("=")
|
|
return [sum_b1, sum_b2, avg_b, sum_s1, sum_s2, avg_s,]
|
|
|
|
|
|
def get_krakenticker(url):
|
|
resp = requests.get(url)
|
|
return resp.json()
|
|
|
|
|
|
def hrule(character):
|
|
print (character*linelen)
|
|
|
|
|
|
def parse_param(argv):
|
|
"""read cmd line params and switches"""
|
|
try:
|
|
opts, args = getopt.getopt(argv, "p:f:hqs", ["pair=", "file=", "help", "quiet", "short", ])
|
|
return opts, args
|
|
except getopt.GetoptError:
|
|
show_usage()
|
|
sys.exit(2)
|
|
|
|
|
|
def show_usage():
|
|
print ("""
|
|
Usage:
|
|
%s -f <csv-file> [-p <KRAKENPAIR>] [--help] [--quiet] [--short]
|
|
|
|
To report only over one pair:
|
|
%s -f <csv-file> --pair XLTCXXBT
|
|
|
|
To save output in a file use shell redirect:
|
|
%s -f <csv-file> > reportfile.txt
|
|
|
|
To print output, pipe it through lp:
|
|
%s -f <csv-file> | lp -d <printer-name> -o fit-to-page
|
|
|
|
""" %(sys.argv[0], sys.argv[0], sys.argv[0], sys.argv[0]) )
|
|
sys.exit(1)
|
|
|
|
|
|
#######################
|
|
# MAIN
|
|
#######################
|
|
if __name__ == '__main__':
|
|
|
|
if len(sys.argv) < 3: show_usage()
|
|
|
|
opts, args = parse_param(sys.argv[1:])
|
|
#print opts, args
|
|
quiet = False
|
|
pair_only = False
|
|
|
|
for opt, arg in opts:
|
|
if opt in ("-h", "--help"):
|
|
show_usage()
|
|
if opt in ("-f", "--file"):
|
|
filename = arg
|
|
if opt in ("-p", "--pair"):
|
|
pair_only = arg
|
|
if opt in ("-q", "--quiet", "-s", "--short"):
|
|
quiet = True
|
|
|
|
data = {}
|
|
krakenprice = get_krakenticker(KRK_TICKER_URL)['result']
|
|
#print krakenprice, type(krakenprice)
|
|
|
|
# loop over all data and sort into pairs
|
|
fh = open(filename, 'r')
|
|
csv_data = csv.DictReader(fh)
|
|
for line in csv_data:
|
|
if not data.has_key(line['pair']):
|
|
data[line['pair']] = []
|
|
data[line['pair']].append(line)
|
|
|
|
# dict of data to hold all totals for all pairs
|
|
result_data = {}
|
|
# loop over each pair
|
|
pairs = data.keys()
|
|
for pair in pairs:
|
|
if pair_only and pair_only != pair:
|
|
print ("Match, abort")
|
|
continue
|
|
print
|
|
price = float(krakenprice[pair]['c'][0].rstrip("0"))
|
|
#print "Current Krakenprice [%s]: %0.6f" %(pair, price,)
|
|
hrule("-")
|
|
print (" "*20 + pair + " [%0.6f]"%price + " "*20)
|
|
hrule("-")
|
|
result_data[pair] = calc_totals(data[pair])
|
|
|
|
profit_buy = ( result_data[pair][0] * price ) - (result_data[pair][0] * result_data[pair][2])
|
|
print ("Profit [BUY] =", profit_buy)
|
|
profit_sell = (result_data[pair][3] * result_data[pair][5]) - ( result_data[pair][3] * price )
|
|
print ("Profit [SELL] =", profit_sell)
|
|
print ("Profit =", profit_buy + profit_sell)
|
|
|
|
hrule("*")
|
|
# results_data is not used yet, maybe removed later
|
|
#print "Result:", result_data
|
|
|