2
2
from poloniex import Poloniex
3
3
from ConfigParser import SafeConfigParser
4
4
from Logger import Logger
5
+ from decimal import *
6
+
7
+ SATOSHI = Decimal (10 ) ** - 8
5
8
6
9
config = SafeConfigParser ()
7
10
config_location = 'default.cfg'
16
19
#sleep between iterations, time in seconds
17
20
sleeptime = 60
18
21
#minimum daily lend rate in percent
19
- mindailyrate = 0.04
22
+ mindailyrate = 0.01
20
23
#max rate. 2% is good choice because it's default at margin trader interface. 5% is max to be accepted by the exchange
21
24
maxdailyrate = 2
22
25
#The number of offers to split the available balance uniformly across the [gaptop, gapbottom] range.
23
26
spreadlend = 3
24
27
#The depth of lendbook (in percent of lendable balance) to move through before placing the first (gapbottom) and last (gaptop) offer.
25
28
#if gapbottom is set to 0, the first offer will be at the lowest possible rate. However some low value is recommended (say 10%) to skip dust offers
26
- gapbottom = 10
27
- gaptop = 200
29
+ gapbottom = 1
30
+ gaptop = 100
28
31
#Daily lend rate threshold after which we offer lends for 60 days as opposed to 2. If set to 0 all offers will be placed for a 2 day period
29
32
sixtydaythreshold = 0.2
30
33
#custom config per coin, useful when closing positions etc.
44
47
45
48
46
49
sleepTime = float (config .get ("BOT" ,"sleeptime" ))
47
- minDailyRate = float (config .get ("BOT" ,"mindailyrate" ))/ 100
48
- maxDailyRate = float (config .get ("BOT" ,"maxdailyrate" ))/ 100
50
+ minDailyRate = Decimal (config .get ("BOT" ,"mindailyrate" ))/ 100
51
+ maxDailyRate = Decimal (config .get ("BOT" ,"maxdailyrate" ))/ 100
49
52
spreadLend = int (config .get ("BOT" ,"spreadlend" ))
50
- gapBottom = float (config .get ("BOT" ,"gapbottom" ))
51
- gapTop = float (config .get ("BOT" ,"gaptop" ))
53
+ gapBottom = Decimal (config .get ("BOT" ,"gapbottom" ))
54
+ gapTop = Decimal (config .get ("BOT" ,"gaptop" ))
52
55
sixtyDayThreshold = float (config .get ("BOT" ,"sixtydaythreshold" ))/ 100
53
56
54
57
try :
57
60
#coinconfig parser
58
61
for cur in coinconfig :
59
62
cur = cur .split (':' )
60
- coincfg [cur [0 ]] = dict (minrate = (float (cur [1 ]))/ 100 , maxactive = float (cur [2 ]))
63
+ coincfg [cur [0 ]] = dict (minrate = (Decimal (cur [1 ]))/ 100 , maxactive = Decimal (cur [2 ]))
61
64
except Exception as e :
62
65
pass
63
66
@@ -89,33 +92,39 @@ def timestamp():
89
92
bot = Poloniex (config .get ("API" ,"apikey" ), config .get ("API" ,"secret" ))
90
93
log = Logger ()
91
94
92
- def totalLended ():
95
+ #total lended global variable
96
+ totalLended = {}
97
+
98
+ def refreshTotalLended ():
99
+ global totalLended
93
100
cryptoLended = bot .returnActiveLoans ()
94
101
95
- allPairs = {}
96
- cryptoLendedSum = float (0 )
102
+ totalLended = {}
103
+ cryptoLendedSum = Decimal (0 )
97
104
98
105
for item in cryptoLended ["provided" ]:
99
106
itemStr = item ["amount" ].encode ("utf-8" )
100
- itemFloat = float (itemStr )
101
- if item ["currency" ] in allPairs :
102
- cryptoLendedSum = allPairs [item ["currency" ]] + itemFloat
103
- allPairs [item ["currency" ]] = cryptoLendedSum
107
+ itemFloat = Decimal (itemStr )
108
+ if item ["currency" ] in totalLended :
109
+ cryptoLendedSum = totalLended [item ["currency" ]] + itemFloat
110
+ totalLended [item ["currency" ]] = cryptoLendedSum
104
111
else :
105
112
cryptoLendedSum = itemFloat
106
- allPairs [item ["currency" ]] = cryptoLendedSum
113
+ totalLended [item ["currency" ]] = cryptoLendedSum
114
+
115
+ def stringifyTotalLended ():
107
116
result = 'Lended: '
108
- for key in sorted (allPairs ):
109
- result += '[' + "%.3f" % float ( allPairs [key ]) + ' '
117
+ for key in sorted (totalLended ):
118
+ result += '[' + "%.3f" % Decimal ( totalLended [key ]) + ' '
110
119
result += key + '] '
111
120
return result
112
121
113
122
def createLoanOffer (cur ,amt ,rate ):
114
123
days = '2'
115
- #if (minDailyRate - 0.000001) < rate and float (amt) > 0.001:
124
+ #if (minDailyRate - 0.000001) < rate and Decimal (amt) > 0.001:
116
125
if float (amt ) > 0.001 :
117
126
rate = float (rate ) - 0.000001 #lend offer just bellow the competing one
118
- amt = "%.8f" % float (amt )
127
+ amt = "%.8f" % Decimal (amt )
119
128
if rate > sixtyDayThreshold :
120
129
days = '60'
121
130
if sixtyDayThreshold == 0 :
@@ -136,7 +145,7 @@ def cancelAndLoanAll():
136
145
onOrderBalances = {}
137
146
for cur in loanOffers :
138
147
for offer in loanOffers [cur ]:
139
- onOrderBalances [cur ] = onOrderBalances .get (cur , 0 ) + float (offer ['amount' ])
148
+ onOrderBalances [cur ] = onOrderBalances .get (cur , 0 ) + Decimal (offer ['amount' ])
140
149
if dryRun == False :
141
150
msg = bot .cancelLoanOffer (cur ,offer ['id' ])
142
151
log .cancelOrders (cur , msg )
@@ -161,76 +170,49 @@ def cancelAndLoanAll():
161
170
log .log ('Using custom mindailyrate ' + str (coincfg [activeCur ]['minrate' ]* 100 ) + '% for ' + activeCur )
162
171
163
172
loans = bot .returnLoanOrders (activeCur )
164
- s = float (0 ) #sum
173
+ s = Decimal (0 ) #sum
165
174
i = int (0 ) #offer book iterator
166
175
j = int (0 ) #spread step count
167
- lent = float (0 )
176
+ lent = Decimal (0 )
168
177
step = (gapTop - gapBottom )/ spreadLend
169
178
#TODO check for minimum lendable amount, and try to decrease the spread. e.g. at the moment balances lower than 0.001 won't be lent
170
179
#in case of empty lendbook, lend at max
180
+ activePlusLended = Decimal (activeBal )
181
+ if activeCur in totalLended :
182
+ activePlusLended += Decimal (totalLended [activeCur ])
171
183
if len (loans ['offers' ]) == 0 :
172
- createLoanOffer (activeCur ,float (activeBal )- lent ,maxDailyRate )
184
+ createLoanOffer (activeCur ,Decimal (activeBal )- lent ,maxDailyRate )
173
185
for offer in loans ['offers' ]:
174
- s = s + float (offer ['amount' ])
186
+ s = s + Decimal (offer ['amount' ])
175
187
s2 = s
176
188
while True :
177
- if s2 > float ( activeBal ) * (gapBottom / 100 + (step / 100 * j )) and float (offer ['rate' ]) > curMinDailyRate :
189
+ if s2 > activePlusLended * (gapBottom / 100 + (step / 100 * j )) and Decimal (offer ['rate' ]) > curMinDailyRate :
178
190
j += 1
179
- #ran into a problem were 14235.82451057 couldn't be lent because of rounding
180
- s2 = s2 + float (activeBal )/ spreadLend - 0.00000001
191
+ s2 = s2 + Decimal (activeBal )/ spreadLend
181
192
else :
182
193
createLoanOffer (activeCur ,s2 - s ,offer ['rate' ])
183
- lent = lent + (s2 - s )
194
+ lent = lent + (s2 - s ). quantize ( SATOSHI )
184
195
break
185
196
if j == spreadLend :
186
- createLoanOffer (activeCur ,float (activeBal )- lent ,offer ['rate' ])
197
+ createLoanOffer (activeCur ,Decimal (activeBal )- lent ,offer ['rate' ])
187
198
break
188
199
if j == spreadLend :
189
200
break
190
201
i += 1
191
202
if i == len (loans ['offers' ]): #end of the offers lend at max
192
- createLoanOffer (activeCur ,float (activeBal )- lent ,maxDailyRate )
193
-
194
- cryptoLendedOld = {u'provided' : []}
195
- cryptoLendedAll = {}
196
-
197
- def profit ():
198
- global cryptoLendedOld
199
- global cryptoLendedAll
200
- cryptoLended = bot .returnActiveLoans ()
201
-
202
- cryptoLendedSum = float (0 )
203
-
204
- for item in cryptoLended ["provided" ]:
205
- for itemOld in cryptoLendedOld ["provided" ]:
206
- if item ["id" ] == itemOld ["id" ]:
207
- itemFloat = float (item ["fees" ].encode ("utf-8" ))
208
- itemFloatOld = float (itemOld ["fees" ].encode ("utf-8" ))
209
- # log.log('Matching Loans: ' + str(item["id"]) + ' ' + str(itemOld["id"]) + ' ' + str(itemFloat) + ' ' + str(itemFloatOld))
210
- if item ["currency" ] in cryptoLendedAll :
211
- cryptoLendedSum = cryptoLendedAll [item ["currency" ]] + itemFloat - itemFloatOld
212
- cryptoLendedAll [item ["currency" ]] = cryptoLendedSum
213
- else :
214
- cryptoLendedSum = itemFloat - itemFloatOld
215
- cryptoLendedAll [item ["currency" ]] = cryptoLendedSum
216
- break
217
- cryptoLendedOld = cryptoLended
218
- result = 'Run-time: '
219
- for key in sorted (cryptoLendedAll ):
220
- result += '[' + "%.8f" % float (cryptoLendedAll [key ]) + ' '
221
- result += key + '] '
222
- return result
203
+ createLoanOffer (activeCur ,Decimal (activeBal )- lent ,maxDailyRate )
223
204
224
205
log .log ('Welcome to Poloniex Lending Bot' )
225
206
226
207
while True :
227
208
try :
228
- log .refreshStatus (totalLended () + profit ())
209
+ refreshTotalLended ()
210
+ log .refreshStatus (stringifyTotalLended ())
229
211
cancelAndLoanAll ()
230
212
except Exception as e :
231
213
log .log ("ERROR: " + str (e ))
232
214
pass
233
215
except KeyboardInterrupt :
234
216
print '\n bye'
235
217
exit (0 )
236
- time .sleep (sleepTime )
218
+ time .sleep (sleepTime )
0 commit comments