Merge with develop

This commit is contained in:
Anton
2018-06-23 16:50:27 +03:00
36 changed files with 1336 additions and 987 deletions

View File

@@ -14,11 +14,11 @@ import requests
from cachetools import TTLCache, cached
from freqtrade import (
DependencyException, OperationalException, TemporaryError,
exchange, persistence, __version__,
DependencyException, OperationalException, TemporaryError, persistence, __version__,
)
from freqtrade import constants
from freqtrade.analyze import Analyze
from freqtrade.exchange import Exchange
from freqtrade.fiat_convert import CryptoToFiatConverter
from freqtrade.persistence import Trade
from freqtrade.rpc.rpc_manager import RPCManager
@@ -54,7 +54,7 @@ class FreqtradeBot(object):
self.fiat_converter = CryptoToFiatConverter()
self.rpc: RPCManager = RPCManager(self)
self.persistence = None
self.exchange = None
self.exchange = Exchange(self.config)
self._init_modules()
@@ -66,7 +66,6 @@ class FreqtradeBot(object):
# Initialize all modules
persistence.init(self.config)
exchange.init(self.config)
# Set initial application state
initial_state = self.config.get('initial_state')
@@ -186,13 +185,13 @@ class FreqtradeBot(object):
:return: List of pairs
"""
if not exchange.exchange_has('fetchTickers'):
if not self.exchange.exchange_has('fetchTickers'):
raise OperationalException(
'Exchange does not support dynamic whitelist.'
'Please edit your config and restart the bot'
)
tickers = exchange.get_tickers()
tickers = self.exchange.get_tickers()
# check length so that we make sure that '/' is actually in the string
tickers = [v for k, v in tickers.items()
if len(k.split('/')) == 2 and k.split('/')[1] == base_currency]
@@ -210,7 +209,7 @@ class FreqtradeBot(object):
black_listed
"""
sanitized_whitelist = whitelist
markets = exchange.get_markets()
markets = self.exchange.get_markets()
markets = [m for m in markets if m['quote'] == self.config['stake_currency']]
known_pairs = set()
@@ -247,7 +246,7 @@ class FreqtradeBot(object):
def _get_trade_stake_amount(self) -> Optional[float]:
stake_amount = self.config['stake_amount']
avaliable_amount = exchange.get_balance(self.config['stake_currency'])
avaliable_amount = self.exchange.get_balance(self.config['stake_currency'])
if stake_amount == constants.UNLIMITED_STAKE_AMOUNT:
open_trades = len(Trade.query.filter(Trade.is_open.is_(True)).all())
@@ -267,7 +266,7 @@ class FreqtradeBot(object):
return stake_amount
def _get_min_pair_stake_amount(self, pair: str, price: float) -> Optional[float]:
markets = exchange.get_markets()
markets = self.exchange.get_markets()
markets = [m for m in markets if m['symbol'] == pair]
if not markets:
raise ValueError(f'Can\'t get market information for symbol {pair}')
@@ -307,7 +306,7 @@ class FreqtradeBot(object):
return False
stake_currency = self.config['stake_currency']
fiat_currency = self.config['fiat_display_currency']
exc_name = exchange.get_name()
exc_name = self.exchange.name
logger.info(
'Checking buy signals to create a new trade with stake_amount: %f ...',
@@ -326,16 +325,17 @@ class FreqtradeBot(object):
# Pick pair based on buy signals
for _pair in whitelist:
(buy, sell) = self.analyze.get_signal(_pair, interval)
(buy, sell) = self.analyze.get_signal(self.exchange, _pair, interval)
if buy and not sell:
pair = _pair
break
else:
return False
pair_s = pair.replace('_', '/')
pair_url = exchange.get_pair_detail_url(pair)
pair_url = self.exchange.get_pair_detail_url(pair)
# Calculate amount
buy_limit = self.get_target_bid(exchange.get_ticker(pair))
buy_limit = self.get_target_bid(self.exchange.get_ticker(pair))
min_stake_amount = self._get_min_pair_stake_amount(pair_s, buy_limit)
if min_stake_amount is not None and min_stake_amount > stake_amount:
@@ -346,7 +346,8 @@ class FreqtradeBot(object):
return False
amount = stake_amount / buy_limit
order_id = exchange.buy(pair, buy_limit, amount)['id']
order_id = self.exchange.buy(pair, buy_limit, amount)['id']
stake_amount_fiat = self.fiat_converter.convert_amount(
stake_amount,
@@ -361,7 +362,7 @@ with limit `{buy_limit:.8f} ({stake_amount:.6f} \
{stake_currency}, {stake_amount_fiat:.3f} {fiat_currency})`"""
)
# Fee is applied twice because we make a LIMIT_BUY and LIMIT_SELL
fee = exchange.get_fee(symbol=pair, taker_or_maker='maker')
fee = self.exchange.get_fee(symbol=pair, taker_or_maker='maker')
trade = Trade(
pair=pair,
stake_amount=stake_amount,
@@ -371,7 +372,7 @@ with limit `{buy_limit:.8f} ({stake_amount:.6f} \
open_rate=buy_limit,
open_rate_requested=buy_limit,
open_date=datetime.utcnow(),
exchange=exchange.get_id(),
exchange=self.exchange.id,
open_order_id=order_id
)
Trade.session.add(trade)
@@ -404,7 +405,7 @@ with limit `{buy_limit:.8f} ({stake_amount:.6f} \
if trade.open_order_id:
# Update trade with order values
logger.info('Found open order for %s', trade)
order = exchange.get_order(trade.open_order_id, trade.pair)
order = self.exchange.get_order(trade.open_order_id, trade.pair)
# Try update amount (binance-fix)
try:
new_amount = self.get_real_amount(trade, order)
@@ -428,7 +429,7 @@ with limit `{buy_limit:.8f} ({stake_amount:.6f} \
def get_real_amount(self, trade: Trade, order: Dict) -> float:
"""
Get real amount for the trade
Necessary for exchanges which charge fees in base currency (e.g. binance)
Necessary for self.exchanges which charge fees in base currency (e.g. binance)
"""
order_amount = order['amount']
# Only run for closed orders
@@ -444,7 +445,8 @@ with limit `{buy_limit:.8f} ({stake_amount:.6f} \
return new_amount
# Fallback to Trades
trades = exchange.get_trades_for_order(trade.open_order_id, trade.pair, trade.open_date)
trades = self.exchange.get_trades_for_order(trade.open_order_id, trade.pair,
trade.open_date)
if len(trades) == 0:
logger.info("Applying fee on amount for %s failed: myTrade-Dict empty found", trade)
@@ -476,12 +478,13 @@ with limit `{buy_limit:.8f} ({stake_amount:.6f} \
raise ValueError(f'attempt to handle closed trade: {trade}')
logger.debug('Handling %s ...', trade)
current_rate = exchange.get_ticker(trade.pair)['bid']
current_rate = self.exchange.get_ticker(trade.pair)['bid']
(buy, sell) = (False, False)
if self.config.get('experimental', {}).get('use_sell_signal'):
(buy, sell) = self.analyze.get_signal(trade.pair, self.analyze.get_ticker_interval())
experimental = self.config.get('experimental', {})
if experimental.get('use_sell_signal') or experimental.get('ignore_roi_if_buy_signal'):
(buy, sell) = self.analyze.get_signal(self.exchange,
trade.pair, self.analyze.get_ticker_interval())
if self.analyze.should_sell(trade, current_rate, datetime.utcnow(), buy, sell):
self.execute_sell(trade, current_rate)
@@ -505,7 +508,7 @@ with limit `{buy_limit:.8f} ({stake_amount:.6f} \
# updated via /forcesell in a different thread.
if not trade.open_order_id:
continue
order = exchange.get_order(trade.open_order_id, trade.pair)
order = self.exchange.get_order(trade.open_order_id, trade.pair)
except requests.exceptions.RequestException:
logger.info(
'Cannot query order for %s due to %s',
@@ -531,7 +534,7 @@ with limit `{buy_limit:.8f} ({stake_amount:.6f} \
:return: True if order was fully cancelled
"""
pair_s = trade.pair.replace('_', '/')
exchange.cancel_order(trade.open_order_id, trade.pair)
self.exchange.cancel_order(trade.open_order_id, trade.pair)
if order['remaining'] == order['amount']:
# if trade is not partially completed, just delete the trade
Trade.session.delete(trade)
@@ -558,7 +561,7 @@ with limit `{buy_limit:.8f} ({stake_amount:.6f} \
pair_s = trade.pair.replace('_', '/')
if order['remaining'] == order['amount']:
# if trade is not partially completed, just cancel the trade
exchange.cancel_order(trade.open_order_id, trade.pair)
self.exchange.cancel_order(trade.open_order_id, trade.pair)
trade.close_rate = None
trade.close_profit = None
trade.close_date = None
@@ -581,15 +584,15 @@ with limit `{buy_limit:.8f} ({stake_amount:.6f} \
exc = trade.exchange
pair = trade.pair
# Execute sell and update trade record
order_id = exchange.sell(str(trade.pair), limit, trade.amount)['id']
order_id = self.exchange.sell(str(trade.pair), limit, trade.amount)['id']
trade.open_order_id = order_id
trade.close_rate_requested = limit
fmt_exp_profit = round(trade.calc_profit_percent(rate=limit) * 100, 2)
profit_trade = trade.calc_profit(rate=limit)
current_rate = exchange.get_ticker(trade.pair)['bid']
current_rate = self.exchange.get_ticker(trade.pair)['bid']
profit = trade.calc_profit_percent(limit)
pair_url = exchange.get_pair_detail_url(trade.pair)
pair_url = self.exchange.get_pair_detail_url(trade.pair)
gain = "profit" if fmt_exp_profit > 0 else "loss"
message = f"*{exc}:* Selling\n" \