Implement buy/sell function and write tests, and add more detailed

exception handling.
This commit is contained in:
enenn 2018-02-07 19:27:31 +01:00
parent 219bd58db1
commit ef7b94310e
6 changed files with 108 additions and 43 deletions

View File

@ -14,3 +14,11 @@ class OperationalException(BaseException):
Requires manual intervention. Requires manual intervention.
This happens when an exchange returns an unexpected error during runtime. This happens when an exchange returns an unexpected error during runtime.
""" """
class NetworkException(BaseException):
"""
Network related error.
This could happen when an exchange is congested, unavailable, or the user
has networking problems. Usually resolves itself after a time.
"""

View File

@ -9,7 +9,7 @@ from datetime import datetime
import arrow import arrow
from cachetools import cached, TTLCache from cachetools import cached, TTLCache
from freqtrade import OperationalException from freqtrade import OperationalException, DependencyException, NetworkException
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -88,7 +88,7 @@ def validate_pairs(pairs: List[str]) -> None:
'Pair {} is not available at {}'.format(pair, _API.id.lower())) 'Pair {} is not available at {}'.format(pair, _API.id.lower()))
def buy(pair: str, rate: float, amount: float) -> str: def buy(pair: str, rate: float, amount: float) -> Dict:
if _CONF['dry_run']: if _CONF['dry_run']:
global _DRY_RUN_OPEN_ORDERS global _DRY_RUN_OPEN_ORDERS
order_id = 'dry_run_buy_{}'.format(randint(0, 10**6)) order_id = 'dry_run_buy_{}'.format(randint(0, 10**6))
@ -101,12 +101,31 @@ def buy(pair: str, rate: float, amount: float) -> str:
'opened': arrow.utcnow().datetime, 'opened': arrow.utcnow().datetime,
'closed': arrow.utcnow().datetime, 'closed': arrow.utcnow().datetime,
} }
return order_id return {'id': order_id}
return _API.buy(pair, rate, amount) try:
return _API.create_limit_buy_order(pair, amount, rate)
except ccxt.InsufficientFunds as e:
raise DependencyException(
'Insufficient funds to create limit buy order on market {}.'
'Tried to buy amount {} at rate {} (total {}).'
'Message: {}'.format(pair, amount, rate, rate*amount, e)
)
except ccxt.InvalidOrder as e:
raise DependencyException(
'Could not create limit buy order on market {}.'
'Tried to buy amount {} at rate {} (total {}).'
'Message: {}'.format(pair, amount, rate, rate*amount, e)
)
except ccxt.NetworkError as e:
raise NetworkException(
'Could not place buy order due to networking error. Message: {}'.format(e)
)
except ccxt.BaseError as e:
raise OperationalException(e)
def sell(pair: str, rate: float, amount: float) -> str: def sell(pair: str, rate: float, amount: float) -> Dict:
if _CONF['dry_run']: if _CONF['dry_run']:
global _DRY_RUN_OPEN_ORDERS global _DRY_RUN_OPEN_ORDERS
order_id = 'dry_run_sell_{}'.format(randint(0, 10**6)) order_id = 'dry_run_sell_{}'.format(randint(0, 10**6))
@ -119,9 +138,28 @@ def sell(pair: str, rate: float, amount: float) -> str:
'opened': arrow.utcnow().datetime, 'opened': arrow.utcnow().datetime,
'closed': arrow.utcnow().datetime, 'closed': arrow.utcnow().datetime,
} }
return order_id return {'id': order_id}
return _API.sell(pair, rate, amount) try:
return _API.create_limit_sell_order(pair, amount, rate)
except ccxt.InsufficientFunds as e:
raise DependencyException(
'Insufficient funds to create limit sell order on market {}.'
'Tried to sell amount {} at rate {} (total {}).'
'Message: {}'.format(pair, amount, rate, rate*amount, e)
)
except ccxt.InvalidOrder as e:
raise DependencyException(
'Could not create limit sell order on market {}.'
'Tried to sell amount {} at rate {} (total {}).'
'Message: {}'.format(pair, amount, rate, rate*amount, e)
)
except ccxt.NetworkError as e:
raise NetworkException(
'Could not place sell order due to networking error. Message: {}'.format(e)
)
except ccxt.BaseError as e:
raise OperationalException(e)
def get_balance(currency: str) -> float: def get_balance(currency: str) -> float:

View File

@ -1,6 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import copy import copy
import json
import logging import logging
import sys import sys
import time import time
@ -12,7 +11,7 @@ import arrow
import requests import requests
from cachetools import cached, TTLCache from cachetools import cached, TTLCache
from freqtrade import (DependencyException, OperationalException, __version__, from freqtrade import (DependencyException, OperationalException, NetworkException, __version__,
exchange, persistence, rpc) exchange, persistence, rpc)
from freqtrade.analyze import get_signal from freqtrade.analyze import get_signal
from freqtrade.fiat_convert import CryptoToFiatConverter from freqtrade.fiat_convert import CryptoToFiatConverter
@ -128,7 +127,7 @@ def _process(interval: int, nb_assets: Optional[int] = 0) -> bool:
check_handle_timedout(_CONF['unfilledtimeout']) check_handle_timedout(_CONF['unfilledtimeout'])
Trade.session.flush() Trade.session.flush()
except (requests.exceptions.RequestException, json.JSONDecodeError) as error: except (NetworkException, DependencyException) as error:
logger.warning( logger.warning(
'Got %s in _process(), retrying in 30 seconds...', 'Got %s in _process(), retrying in 30 seconds...',
error error
@ -231,7 +230,8 @@ def execute_sell(trade: Trade, limit: float) -> None:
:return: None :return: None
""" """
# Execute sell and update trade record # Execute sell and update trade record
order_id = exchange.sell(str(trade.pair), limit, trade.amount) order = exchange.sell(str(trade.pair), limit, trade.amount)
order_id = order['id']
trade.open_order_id = order_id trade.open_order_id = order_id
fmt_exp_profit = round(trade.calc_profit_percent(rate=limit) * 100, 2) fmt_exp_profit = round(trade.calc_profit_percent(rate=limit) * 100, 2)
@ -404,7 +404,8 @@ def create_trade(stake_amount: float, interval: int) -> bool:
buy_limit = get_target_bid(exchange.get_ticker(pair)) buy_limit = get_target_bid(exchange.get_ticker(pair))
amount = stake_amount / buy_limit amount = stake_amount / buy_limit
order_id = exchange.buy(pair, buy_limit, amount) order = exchange.buy(pair, buy_limit, amount)
order_id = order['id']
fiat_converter = CryptoToFiatConverter() fiat_converter = CryptoToFiatConverter()
stake_amount_fiat = fiat_converter.convert_amount( stake_amount_fiat = fiat_converter.convert_amount(

View File

@ -90,38 +90,58 @@ def test_buy_dry_run(default_conf, mocker):
default_conf['dry_run'] = True default_conf['dry_run'] = True
mocker.patch.dict('freqtrade.exchange._CONF', default_conf) mocker.patch.dict('freqtrade.exchange._CONF', default_conf)
assert 'dry_run_buy_' in buy(pair='ETH/BTC', rate=200, amount=1) order = buy(pair='ETH/BTC', rate=200, amount=1)
assert 'id' in order
assert 'dry_run_buy_' in order['id']
def test_buy_prod(default_conf, mocker): def test_buy_prod(default_conf, mocker):
api_mock = MagicMock() api_mock = MagicMock()
api_mock.buy = MagicMock( order_id = 'test_prod_buy_{}'.format(randint(0, 10 ** 6))
return_value='dry_run_buy_{}'.format(randint(0, 10 ** 6))) api_mock.create_limit_buy_order = MagicMock(return_value={
'id': order_id,
'info': {
'foo': 'bar'
}
})
mocker.patch('freqtrade.exchange._API', api_mock) mocker.patch('freqtrade.exchange._API', api_mock)
default_conf['dry_run'] = False default_conf['dry_run'] = False
mocker.patch.dict('freqtrade.exchange._CONF', default_conf) mocker.patch.dict('freqtrade.exchange._CONF', default_conf)
assert 'dry_run_buy_' in buy(pair='ETH/BTC', rate=200, amount=1) order = buy(pair='ETH/BTC', rate=200, amount=1)
assert 'id' in order
assert 'info' in order
assert order['id'] == order_id
def test_sell_dry_run(default_conf, mocker): def test_sell_dry_run(default_conf, mocker):
default_conf['dry_run'] = True default_conf['dry_run'] = True
mocker.patch.dict('freqtrade.exchange._CONF', default_conf) mocker.patch.dict('freqtrade.exchange._CONF', default_conf)
assert 'dry_run_sell_' in sell(pair='ETH/BTC', rate=200, amount=1) order = sell(pair='ETH/BTC', rate=200, amount=1)
assert 'id' in order
assert 'dry_run_sell_' in order['id']
def test_sell_prod(default_conf, mocker): def test_sell_prod(default_conf, mocker):
api_mock = MagicMock() api_mock = MagicMock()
api_mock.sell = MagicMock( order_id = 'test_prod_sell_{}'.format(randint(0, 10 ** 6))
return_value='dry_run_sell_{}'.format(randint(0, 10 ** 6))) api_mock.create_limit_sell_order = MagicMock(return_value={
'id': order_id,
'info': {
'foo': 'bar'
}
})
mocker.patch('freqtrade.exchange._API', api_mock) mocker.patch('freqtrade.exchange._API', api_mock)
default_conf['dry_run'] = False default_conf['dry_run'] = False
mocker.patch.dict('freqtrade.exchange._CONF', default_conf) mocker.patch.dict('freqtrade.exchange._CONF', default_conf)
assert 'dry_run_sell_' in sell(pair='ETH/BTC', rate=200, amount=1) order = sell(pair='ETH/BTC', rate=200, amount=1)
assert 'id' in order
assert 'info' in order
assert order['id'] == order_id
def test_get_balance_dry_run(default_conf, mocker): def test_get_balance_dry_run(default_conf, mocker):
@ -301,7 +321,6 @@ def test_get_fee(default_conf, mocker):
mocker.patch('freqtrade.exchange._API', api_mock) mocker.patch('freqtrade.exchange._API', api_mock)
assert get_fee() == 0.025 assert get_fee() == 0.025
# TODO: disable until caching implemented # TODO: disable until caching implemented
# def test_exchange_misc(mocker): # def test_exchange_misc(mocker):
# api_mock = MagicMock() # api_mock = MagicMock()

View File

@ -124,7 +124,7 @@ def test_status_table_handle(default_conf, update, ticker, mocker):
mocker.patch.multiple('freqtrade.main.exchange', mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(), validate_pairs=MagicMock(),
get_ticker=ticker, get_ticker=ticker,
buy=MagicMock(return_value='mocked_order_id')) buy=MagicMock(return_value={'id': 'mocked_order_id'}))
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
update_state(State.STOPPED) update_state(State.STOPPED)
_status_table(bot=MagicMock(), update=update) _status_table(bot=MagicMock(), update=update)
@ -524,7 +524,7 @@ def test_count_handle(default_conf, update, ticker, mocker):
mocker.patch.multiple('freqtrade.main.exchange', mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(), validate_pairs=MagicMock(),
get_ticker=ticker, get_ticker=ticker,
buy=MagicMock(return_value='mocked_order_id')) buy=MagicMock(return_value={'id': 'mocked_order_id'}))
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
update_state(State.STOPPED) update_state(State.STOPPED)
_count(bot=MagicMock(), update=update) _count(bot=MagicMock(), update=update)

View File

@ -5,12 +5,11 @@ from unittest.mock import MagicMock
import arrow import arrow
import pytest import pytest
import requests
from sqlalchemy import create_engine from sqlalchemy import create_engine
import freqtrade.main as main import freqtrade.main as main
import freqtrade.tests.conftest as tt # test tools import freqtrade.tests.conftest as tt # test tools
from freqtrade import DependencyException, OperationalException from freqtrade import DependencyException, OperationalException, NetworkException
from freqtrade.main import (_process, check_handle_timedout, create_trade, from freqtrade.main import (_process, check_handle_timedout, create_trade,
execute_sell, get_target_bid, handle_trade, init) execute_sell, get_target_bid, handle_trade, init)
from freqtrade.misc import State, get_state from freqtrade.misc import State, get_state
@ -81,7 +80,7 @@ def test_process_trade_creation(default_conf, ticker, limit_buy_order, health, m
mocker.patch.multiple('freqtrade.main.exchange', mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(), validate_pairs=MagicMock(),
get_ticker=ticker, get_ticker=ticker,
buy=MagicMock(return_value='mocked_limit_buy'), buy=MagicMock(return_value={'id': 'mocked_limit_buy'}),
get_order=MagicMock(return_value=limit_buy_order)) get_order=MagicMock(return_value=limit_buy_order))
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
@ -111,7 +110,7 @@ def test_process_exchange_failures(default_conf, ticker, health, mocker):
mocker.patch.multiple('freqtrade.main.exchange', mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(), validate_pairs=MagicMock(),
get_ticker=ticker, get_ticker=ticker,
buy=MagicMock(side_effect=requests.exceptions.RequestException)) buy=MagicMock(side_effect=NetworkException))
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
result = _process(interval=default_conf['ticker_interval']) result = _process(interval=default_conf['ticker_interval'])
assert result is False assert result is False
@ -143,7 +142,7 @@ def test_process_trade_handling(default_conf, ticker, limit_buy_order, health, m
mocker.patch.multiple('freqtrade.main.exchange', mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(), validate_pairs=MagicMock(),
get_ticker=ticker, get_ticker=ticker,
buy=MagicMock(return_value='mocked_limit_buy'), buy=MagicMock(return_value={'id': 'mocked_limit_buy'}),
get_order=MagicMock(return_value=limit_buy_order)) get_order=MagicMock(return_value=limit_buy_order))
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
@ -165,7 +164,7 @@ def test_create_trade(default_conf, ticker, limit_buy_order, mocker):
mocker.patch.multiple('freqtrade.main.exchange', mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(), validate_pairs=MagicMock(),
get_ticker=ticker, get_ticker=ticker,
buy=MagicMock(return_value='mocked_limit_buy')) buy=MagicMock(return_value={'id': 'mocked_limit_buy'}))
# Save state of current whitelist # Save state of current whitelist
whitelist = copy.deepcopy(default_conf['exchange']['pair_whitelist']) whitelist = copy.deepcopy(default_conf['exchange']['pair_whitelist'])
@ -193,7 +192,7 @@ def test_create_trade_minimal_amount(default_conf, ticker, mocker):
mocker.patch.multiple('freqtrade.rpc', init=MagicMock(), send_msg=MagicMock()) mocker.patch.multiple('freqtrade.rpc', init=MagicMock(), send_msg=MagicMock())
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: (True, False)) mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: (True, False))
buy_mock = mocker.patch( buy_mock = mocker.patch(
'freqtrade.main.exchange.buy', MagicMock(return_value='mocked_limit_buy') 'freqtrade.main.exchange.buy', MagicMock(return_value={'id': 'mocked_limit_buy'})
) )
mocker.patch.multiple('freqtrade.main.exchange', mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(), validate_pairs=MagicMock(),
@ -212,7 +211,7 @@ def test_create_trade_no_stake_amount(default_conf, ticker, mocker):
mocker.patch.multiple('freqtrade.main.exchange', mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(), validate_pairs=MagicMock(),
get_ticker=ticker, get_ticker=ticker,
buy=MagicMock(return_value='mocked_limit_buy'), buy=MagicMock(return_value={'id': 'mocked_limit_buy'}),
get_balance=MagicMock(return_value=default_conf['stake_amount'] * 0.5)) get_balance=MagicMock(return_value=default_conf['stake_amount'] * 0.5))
with pytest.raises(DependencyException, match=r'.*stake amount.*'): with pytest.raises(DependencyException, match=r'.*stake amount.*'):
create_trade(default_conf['stake_amount'], default_conf['ticker_interval']) create_trade(default_conf['stake_amount'], default_conf['ticker_interval'])
@ -225,7 +224,7 @@ def test_create_trade_no_pairs(default_conf, ticker, mocker):
mocker.patch.multiple('freqtrade.main.exchange', mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(), validate_pairs=MagicMock(),
get_ticker=ticker, get_ticker=ticker,
buy=MagicMock(return_value='mocked_limit_buy')) buy=MagicMock(return_value={'id': 'mocked_limit_buy'}))
with pytest.raises(DependencyException, match=r'.*No pair in whitelist.*'): with pytest.raises(DependencyException, match=r'.*No pair in whitelist.*'):
conf = copy.deepcopy(default_conf) conf = copy.deepcopy(default_conf)
@ -241,7 +240,7 @@ def test_create_trade_no_pairs_after_blacklist(default_conf, ticker, mocker):
mocker.patch.multiple('freqtrade.main.exchange', mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(), validate_pairs=MagicMock(),
get_ticker=ticker, get_ticker=ticker,
buy=MagicMock(return_value='mocked_limit_buy')) buy=MagicMock(return_value={'id': 'mocked_limit_buy'}))
with pytest.raises(DependencyException, match=r'.*No pair in whitelist.*'): with pytest.raises(DependencyException, match=r'.*No pair in whitelist.*'):
conf = copy.deepcopy(default_conf) conf = copy.deepcopy(default_conf)
@ -277,8 +276,8 @@ def test_handle_trade(default_conf, limit_buy_order, limit_sell_order, mocker):
'last': 0.00001172 'last': 0.00001172
}), }),
get_fee=MagicMock(return_value=0.0025), get_fee=MagicMock(return_value=0.0025),
buy=MagicMock(return_value='mocked_limit_buy'), buy=MagicMock(return_value={'id': 'mocked_limit_buy'}),
sell=MagicMock(return_value='mocked_limit_sell')) sell=MagicMock(return_value={'id': 'mocked_limit_sell'}))
mocker.patch.multiple('freqtrade.fiat_convert.Pymarketcap', mocker.patch.multiple('freqtrade.fiat_convert.Pymarketcap',
ticker=MagicMock(return_value={'price_usd': 15000.0}), ticker=MagicMock(return_value={'price_usd': 15000.0}),
_cache_symbols=MagicMock(return_value={'BTC': 1})) _cache_symbols=MagicMock(return_value={'BTC': 1}))
@ -313,7 +312,7 @@ def test_handle_overlpapping_signals(default_conf, ticker, mocker):
mocker.patch.multiple('freqtrade.main.exchange', mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(), validate_pairs=MagicMock(),
get_ticker=ticker, get_ticker=ticker,
buy=MagicMock(return_value='mocked_limit_buy')) buy=MagicMock(return_value={'id': 'mocked_limit_buy'}))
mocker.patch('freqtrade.main.min_roi_reached', return_value=False) mocker.patch('freqtrade.main.min_roi_reached', return_value=False)
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
@ -363,7 +362,7 @@ def test_handle_trade_roi(default_conf, ticker, mocker, caplog):
mocker.patch.multiple('freqtrade.main.exchange', mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(), validate_pairs=MagicMock(),
get_ticker=ticker, get_ticker=ticker,
buy=MagicMock(return_value='mocked_limit_buy')) buy=MagicMock(return_value={'id': 'mocked_limit_buy'}))
mocker.patch('freqtrade.main.min_roi_reached', return_value=True) mocker.patch('freqtrade.main.min_roi_reached', return_value=True)
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
@ -395,7 +394,7 @@ def test_handle_trade_experimental(default_conf, ticker, mocker, caplog):
mocker.patch.multiple('freqtrade.main.exchange', mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(), validate_pairs=MagicMock(),
get_ticker=ticker, get_ticker=ticker,
buy=MagicMock(return_value='mocked_limit_buy')) buy=MagicMock(return_value={'id': 'mocked_limit_buy'}))
mocker.patch('freqtrade.main.min_roi_reached', return_value=False) mocker.patch('freqtrade.main.min_roi_reached', return_value=False)
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
@ -420,7 +419,7 @@ def test_close_trade(default_conf, ticker, limit_buy_order, limit_sell_order, mo
mocker.patch.multiple('freqtrade.main.exchange', mocker.patch.multiple('freqtrade.main.exchange',
validate_pairs=MagicMock(), validate_pairs=MagicMock(),
get_ticker=ticker, get_ticker=ticker,
buy=MagicMock(return_value='mocked_limit_buy')) buy=MagicMock(return_value={'id': 'mocked_limit_buy'}))
# Create trade and sell it # Create trade and sell it
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
@ -747,7 +746,7 @@ def test_sell_profit_only_enable_profit(default_conf, limit_buy_order, mocker):
'last': 0.00002172 'last': 0.00002172
}), }),
get_fee=MagicMock(return_value=0.0025), get_fee=MagicMock(return_value=0.0025),
buy=MagicMock(return_value='mocked_limit_buy')) buy=MagicMock(return_value={'id': 'mocked_limit_buy'}))
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
create_trade(0.001, default_conf['ticker_interval']) create_trade(0.001, default_conf['ticker_interval'])
@ -776,7 +775,7 @@ def test_sell_profit_only_disable_profit(default_conf, limit_buy_order, mocker):
'last': 0.00002172 'last': 0.00002172
}), }),
get_fee=MagicMock(return_value=0.0025), get_fee=MagicMock(return_value=0.0025),
buy=MagicMock(return_value='mocked_limit_buy')) buy=MagicMock(return_value={'id': 'mocked_limit_buy'}))
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
create_trade(0.001, default_conf['ticker_interval']) create_trade(0.001, default_conf['ticker_interval'])
@ -805,7 +804,7 @@ def test_sell_profit_only_enable_loss(default_conf, limit_buy_order, mocker):
'last': 0.00000172 'last': 0.00000172
}), }),
get_fee=MagicMock(return_value=0.0025), get_fee=MagicMock(return_value=0.0025),
buy=MagicMock(return_value='mocked_limit_buy')) buy=MagicMock(return_value={'id': 'mocked_limit_buy'}))
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
create_trade(0.001, default_conf['ticker_interval']) create_trade(0.001, default_conf['ticker_interval'])
@ -834,7 +833,7 @@ def test_sell_profit_only_disable_loss(default_conf, limit_buy_order, mocker):
'last': 0.00000172 'last': 0.00000172
}), }),
get_fee=MagicMock(return_value=0.0025), get_fee=MagicMock(return_value=0.0025),
buy=MagicMock(return_value='mocked_limit_buy')) buy=MagicMock(return_value={'id': 'mocked_limit_buy'}))
init(default_conf, create_engine('sqlite://')) init(default_conf, create_engine('sqlite://'))
create_trade(0.001, default_conf['ticker_interval']) create_trade(0.001, default_conf['ticker_interval'])