22from poloniex import Poloniex
33from ConfigParser import SafeConfigParser
44from Logger import Logger
5+ from decimal import *
6+
7+ SATOSHI = Decimal (10 ) ** - 8
58
69config = SafeConfigParser ()
710config_location = 'default.cfg'
1619#sleep between iterations, time in seconds
1720sleeptime = 60
1821#minimum daily lend rate in percent
19- mindailyrate = 0.04
22+ mindailyrate = 0.01
2023#max rate. 2% is good choice because it's default at margin trader interface. 5% is max to be accepted by the exchange
2124maxdailyrate = 2
2225#The number of offers to split the available balance uniformly across the [gaptop, gapbottom] range.
2326spreadlend = 3
2427#The depth of lendbook (in percent of lendable balance) to move through before placing the first (gapbottom) and last (gaptop) offer.
2528#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
2831#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
2932sixtydaythreshold = 0.2
3033#custom config per coin, useful when closing positions etc.
4447
4548
4649sleepTime = 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
4952spreadLend = 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" ))
5255sixtyDayThreshold = float (config .get ("BOT" ,"sixtydaythreshold" ))/ 100
5356
5457try :
5760 #coinconfig parser
5861 for cur in coinconfig :
5962 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 ]))
6164except Exception as e :
6265 pass
6366
@@ -89,33 +92,39 @@ def timestamp():
8992bot = Poloniex (config .get ("API" ,"apikey" ), config .get ("API" ,"secret" ))
9093log = Logger ()
9194
92- def totalLended ():
95+ #total lended global variable
96+ totalLended = {}
97+
98+ def refreshTotalLended ():
99+ global totalLended
93100 cryptoLended = bot .returnActiveLoans ()
94101
95- allPairs = {}
96- cryptoLendedSum = float (0 )
102+ totalLended = {}
103+ cryptoLendedSum = Decimal (0 )
97104
98105 for item in cryptoLended ["provided" ]:
99106 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
104111 else :
105112 cryptoLendedSum = itemFloat
106- allPairs [item ["currency" ]] = cryptoLendedSum
113+ totalLended [item ["currency" ]] = cryptoLendedSum
114+
115+ def stringifyTotalLended ():
107116 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 ]) + ' '
110119 result += key + '] '
111120 return result
112121
113122def createLoanOffer (cur ,amt ,rate ):
114123 days = '2'
115- #if (minDailyRate - 0.000001) < rate and float (amt) > 0.001:
124+ #if (minDailyRate - 0.000001) < rate and Decimal (amt) > 0.001:
116125 if float (amt ) > 0.001 :
117126 rate = float (rate ) - 0.000001 #lend offer just bellow the competing one
118- amt = "%.8f" % float (amt )
127+ amt = "%.8f" % Decimal (amt )
119128 if rate > sixtyDayThreshold :
120129 days = '60'
121130 if sixtyDayThreshold == 0 :
@@ -136,7 +145,7 @@ def cancelAndLoanAll():
136145 onOrderBalances = {}
137146 for cur in loanOffers :
138147 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' ])
140149 if dryRun == False :
141150 msg = bot .cancelLoanOffer (cur ,offer ['id' ])
142151 log .cancelOrders (cur , msg )
@@ -161,76 +170,49 @@ def cancelAndLoanAll():
161170 log .log ('Using custom mindailyrate ' + str (coincfg [activeCur ]['minrate' ]* 100 ) + '% for ' + activeCur )
162171
163172 loans = bot .returnLoanOrders (activeCur )
164- s = float (0 ) #sum
173+ s = Decimal (0 ) #sum
165174 i = int (0 ) #offer book iterator
166175 j = int (0 ) #spread step count
167- lent = float (0 )
176+ lent = Decimal (0 )
168177 step = (gapTop - gapBottom )/ spreadLend
169178 #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
170179 #in case of empty lendbook, lend at max
180+ activePlusLended = Decimal (activeBal )
181+ if activeCur in totalLended :
182+ activePlusLended += Decimal (totalLended [activeCur ])
171183 if len (loans ['offers' ]) == 0 :
172- createLoanOffer (activeCur ,float (activeBal )- lent ,maxDailyRate )
184+ createLoanOffer (activeCur ,Decimal (activeBal )- lent ,maxDailyRate )
173185 for offer in loans ['offers' ]:
174- s = s + float (offer ['amount' ])
186+ s = s + Decimal (offer ['amount' ])
175187 s2 = s
176188 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 :
178190 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
181192 else :
182193 createLoanOffer (activeCur ,s2 - s ,offer ['rate' ])
183- lent = lent + (s2 - s )
194+ lent = lent + (s2 - s ). quantize ( SATOSHI )
184195 break
185196 if j == spreadLend :
186- createLoanOffer (activeCur ,float (activeBal )- lent ,offer ['rate' ])
197+ createLoanOffer (activeCur ,Decimal (activeBal )- lent ,offer ['rate' ])
187198 break
188199 if j == spreadLend :
189200 break
190201 i += 1
191202 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 )
223204
224205log .log ('Welcome to Poloniex Lending Bot' )
225206
226207while True :
227208 try :
228- log .refreshStatus (totalLended () + profit ())
209+ refreshTotalLended ()
210+ log .refreshStatus (stringifyTotalLended ())
229211 cancelAndLoanAll ()
230212 except Exception as e :
231213 log .log ("ERROR: " + str (e ))
232214 pass
233215 except KeyboardInterrupt :
234216 print '\n bye'
235217 exit (0 )
236- time .sleep (sleepTime )
218+ time .sleep (sleepTime )
0 commit comments