Recommitted as new branch with unit tests - GIT screwd me on the last PR
This commit is contained in:
parent
f832edf5bc
commit
012fe94333
@ -4,6 +4,7 @@ import logging
|
|||||||
from random import randint
|
from random import randint
|
||||||
from typing import List, Dict, Any, Optional
|
from typing import List, Dict, Any, Optional
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from math import floor, ceil
|
||||||
|
|
||||||
import ccxt
|
import ccxt
|
||||||
import arrow
|
import arrow
|
||||||
@ -150,6 +151,28 @@ class Exchange(object):
|
|||||||
"""
|
"""
|
||||||
return endpoint in self._api.has and self._api.has[endpoint]
|
return endpoint in self._api.has and self._api.has[endpoint]
|
||||||
|
|
||||||
|
def symbol_amount_prec(self, pair, amount: float):
|
||||||
|
'''
|
||||||
|
Returns the amount to buy or sell to a precision the Exchange accepts
|
||||||
|
Rounded down
|
||||||
|
'''
|
||||||
|
if self._api.markets[pair]['precision']['amount']:
|
||||||
|
symbol_prec = self._api.markets[pair]['precision']['amount']
|
||||||
|
big_amount = amount * pow(10, symbol_prec)
|
||||||
|
amount = floor(big_amount) / pow(10, symbol_prec)
|
||||||
|
return amount
|
||||||
|
|
||||||
|
def symbol_price_prec(self, pair, price: float):
|
||||||
|
'''
|
||||||
|
Returns the price buying or selling with to the precision the Exchange accepts
|
||||||
|
Rounds up
|
||||||
|
'''
|
||||||
|
if self._api.markets[pair]['precision']['price']:
|
||||||
|
symbol_prec = self._api.markets[pair]['precision']['price']
|
||||||
|
big_price = price * pow(10, symbol_prec)
|
||||||
|
price = ceil(big_price) / pow(10, symbol_prec)
|
||||||
|
return price
|
||||||
|
|
||||||
def buy(self, pair: str, rate: float, amount: float) -> Dict:
|
def buy(self, pair: str, rate: float, amount: float) -> Dict:
|
||||||
if self._conf['dry_run']:
|
if self._conf['dry_run']:
|
||||||
order_id = f'dry_run_buy_{randint(0, 10**6)}'
|
order_id = f'dry_run_buy_{randint(0, 10**6)}'
|
||||||
@ -167,6 +190,10 @@ class Exchange(object):
|
|||||||
return {'id': order_id}
|
return {'id': order_id}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
# Set the precision for amount and price(rate) as accepted by the exchange
|
||||||
|
amount = self.symbol_amount_prec(pair, amount)
|
||||||
|
rate = self.symbol_price_prec(pair, rate)
|
||||||
|
|
||||||
return self._api.create_limit_buy_order(pair, amount, rate)
|
return self._api.create_limit_buy_order(pair, amount, rate)
|
||||||
except ccxt.InsufficientFunds as e:
|
except ccxt.InsufficientFunds as e:
|
||||||
raise DependencyException(
|
raise DependencyException(
|
||||||
@ -200,6 +227,10 @@ class Exchange(object):
|
|||||||
return {'id': order_id}
|
return {'id': order_id}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
# Set the precision for amount and price(rate) as accepted by the exchange
|
||||||
|
amount = self.symbol_amount_prec(pair, amount)
|
||||||
|
rate = self.symbol_price_prec(pair, rate)
|
||||||
|
|
||||||
return self._api.create_limit_sell_order(pair, amount, rate)
|
return self._api.create_limit_sell_order(pair, amount, rate)
|
||||||
except ccxt.InsufficientFunds as e:
|
except ccxt.InsufficientFunds as e:
|
||||||
raise DependencyException(
|
raise DependencyException(
|
||||||
|
@ -52,6 +52,52 @@ def test_init_exception(default_conf, mocker):
|
|||||||
Exchange(default_conf)
|
Exchange(default_conf)
|
||||||
|
|
||||||
|
|
||||||
|
def test_symbol_amount_prec(default_conf, mocker):
|
||||||
|
'''
|
||||||
|
Test rounds down to 4 Decimal places
|
||||||
|
'''
|
||||||
|
api_mock = MagicMock()
|
||||||
|
api_mock.load_markets = MagicMock(return_value={
|
||||||
|
'ETH/BTC': '', 'LTC/BTC': '', 'XRP/BTC': '', 'NEO/BTC': ''
|
||||||
|
})
|
||||||
|
mocker.patch('freqtrade.exchange.Exchange.name', PropertyMock(return_value='binance'))
|
||||||
|
|
||||||
|
markets = PropertyMock(return_value={'ETH/BTC': {'precision': {'amount': 4}}})
|
||||||
|
type(api_mock).markets = markets
|
||||||
|
|
||||||
|
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock))
|
||||||
|
mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock())
|
||||||
|
exchange = Exchange(default_conf)
|
||||||
|
|
||||||
|
amount = 2.34559
|
||||||
|
pair = 'ETH/BTC'
|
||||||
|
amount = exchange.symbol_amount_prec(pair, amount)
|
||||||
|
assert amount == 2.3455
|
||||||
|
|
||||||
|
|
||||||
|
def test_symbol_price_prec(default_conf, mocker):
|
||||||
|
'''
|
||||||
|
Test rounds up to 4 decimal places
|
||||||
|
'''
|
||||||
|
api_mock = MagicMock()
|
||||||
|
api_mock.load_markets = MagicMock(return_value={
|
||||||
|
'ETH/BTC': '', 'LTC/BTC': '', 'XRP/BTC': '', 'NEO/BTC': ''
|
||||||
|
})
|
||||||
|
mocker.patch('freqtrade.exchange.Exchange.name', PropertyMock(return_value='binance'))
|
||||||
|
|
||||||
|
markets = PropertyMock(return_value={'ETH/BTC': {'precision': {'price': 4}}})
|
||||||
|
type(api_mock).markets = markets
|
||||||
|
|
||||||
|
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock))
|
||||||
|
mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock())
|
||||||
|
exchange = Exchange(default_conf)
|
||||||
|
|
||||||
|
price = 2.34559
|
||||||
|
pair = 'ETH/BTC'
|
||||||
|
price = exchange.symbol_price_prec(pair, price)
|
||||||
|
assert price == 2.3456
|
||||||
|
|
||||||
|
|
||||||
def test_validate_pairs(default_conf, mocker):
|
def test_validate_pairs(default_conf, mocker):
|
||||||
api_mock = MagicMock()
|
api_mock = MagicMock()
|
||||||
api_mock.load_markets = MagicMock(return_value={
|
api_mock.load_markets = MagicMock(return_value={
|
||||||
@ -173,7 +219,7 @@ def test_validate_timeframes_not_in_config(default_conf, mocker):
|
|||||||
Exchange(default_conf)
|
Exchange(default_conf)
|
||||||
|
|
||||||
|
|
||||||
def test_exchange_has(default_conf, mocker):
|
def test_exchangehas(default_conf, mocker):
|
||||||
exchange = get_patched_exchange(mocker, default_conf)
|
exchange = get_patched_exchange(mocker, default_conf)
|
||||||
assert not exchange.exchange_has('ASDFASDF')
|
assert not exchange.exchange_has('ASDFASDF')
|
||||||
api_mock = MagicMock()
|
api_mock = MagicMock()
|
||||||
|
Loading…
Reference in New Issue
Block a user