Display profits in fiat
This commit is contained in:
parent
433bf409f4
commit
ff6b0fc1c9
@ -55,6 +55,12 @@ use the `last` price and values between those interpolate between ask and last
|
||||
price. Using `ask` price will guarantee quick success in bid, but bot will also
|
||||
end up paying more then would probably have been necessary.
|
||||
|
||||
`fiat_currency` set the fiat to use for the conversion form coin to
|
||||
fiat in Telegram. The valid value are: "AUD", "BRL", "CAD", "CHF",
|
||||
"CLP", "CNY", "CZK", "DKK", "EUR", "GBP", "HKD", "HUF", "IDR", "ILS",
|
||||
"INR", "JPY", "KRW", "MXN", "MYR", "NOK", "NZD", "PHP", "PKR", "PLN",
|
||||
"RUB", "SEK", "SGD", "THB", "TRY", "TWD", "ZAR", "USD".
|
||||
|
||||
The other values should be self-explanatory,
|
||||
if not feel free to raise a github issue.
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
"max_open_trades": 3,
|
||||
"stake_currency": "BTC",
|
||||
"stake_amount": 0.05,
|
||||
"fiat_display_currency": "USD",
|
||||
"dry_run": false,
|
||||
"minimal_roi": {
|
||||
"40": 0.0,
|
||||
|
156
freqtrade/fiat_convert.py
Normal file
156
freqtrade/fiat_convert.py
Normal file
@ -0,0 +1,156 @@
|
||||
import logging
|
||||
import time
|
||||
from pymarketcap import Pymarketcap
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class CryptoFiat():
|
||||
# Constants
|
||||
CACHE_DURATION = 6 * 60 * 60 # 6 hours
|
||||
|
||||
def __init__(self, crypto_symbol: str, fiat_symbol: str, price: float) -> None:
|
||||
"""
|
||||
Create an object that will contains the price for a crypto-currency in fiat
|
||||
:param crypto_symbol: Crypto-currency you want to convert (e.g BTC)
|
||||
:param fiat_symbol: FIAT currency you want to convert to (e.g USD)
|
||||
:param price: Price in FIAT
|
||||
"""
|
||||
|
||||
# Public attributes
|
||||
self.crypto_symbol = None
|
||||
self.fiat_symbol = None
|
||||
self.price = 0.0
|
||||
|
||||
# Private attributes
|
||||
self._expiration = 0
|
||||
|
||||
self.crypto_symbol = crypto_symbol.upper()
|
||||
self.fiat_symbol = fiat_symbol.upper()
|
||||
self.set_price(price=price)
|
||||
|
||||
def set_price(self, price: float) -> None:
|
||||
"""
|
||||
Set the price of the Crypto-currency in FIAT and set the expiration time
|
||||
:param price: Price of the current Crypto currency in the fiat
|
||||
:return: None
|
||||
"""
|
||||
self.price = price
|
||||
self._expiration = time.time() + self.CACHE_DURATION
|
||||
|
||||
def is_expired(self) -> bool:
|
||||
"""
|
||||
Return if the current price is still valid or needs to be refreshed
|
||||
:return: bool, true the price is expired and needs to be refreshed, false the price is
|
||||
still valid
|
||||
"""
|
||||
return self._expiration - time.time() <= 0
|
||||
|
||||
|
||||
class CryptoToFiatConverter():
|
||||
# Constants
|
||||
SUPPORTED_FIAT = [
|
||||
"AUD", "BRL", "CAD", "CHF", "CLP", "CNY", "CZK", "DKK",
|
||||
"EUR", "GBP", "HKD", "HUF", "IDR", "ILS", "INR", "JPY",
|
||||
"KRW", "MXN", "MYR", "NOK", "NZD", "PHP", "PKR", "PLN",
|
||||
"RUB", "SEK", "SGD", "THB", "TRY", "TWD", "ZAR", "USD"
|
||||
]
|
||||
|
||||
def __init__(self) -> None:
|
||||
self._coinmarketcap = Pymarketcap()
|
||||
self._pairs = []
|
||||
|
||||
def convert_amount(self, crypto_amount: float, crypto_symbol: str, fiat_symbol: str) -> float:
|
||||
"""
|
||||
Convert an amount of crypto-currency to fiat
|
||||
:param crypto_amount: amount of crypto-currency to convert
|
||||
:param crypto_symbol: crypto-currency used
|
||||
:param fiat_symbol: fiat to convert to
|
||||
:return: float, value in fiat of the crypto-currency amount
|
||||
"""
|
||||
price = self.get_price(crypto_symbol=crypto_symbol, fiat_symbol=fiat_symbol)
|
||||
return float(crypto_amount) * float(price)
|
||||
|
||||
def get_price(self, crypto_symbol: str, fiat_symbol: str) -> float:
|
||||
"""
|
||||
Return the price of the Crypto-currency in Fiat
|
||||
:param crypto_symbol: Crypto-currency you want to convert (e.g BTC)
|
||||
:param fiat_symbol: FIAT currency you want to convert to (e.g USD)
|
||||
:return: Price in FIAT
|
||||
"""
|
||||
crypto_symbol = crypto_symbol.upper()
|
||||
fiat_symbol = fiat_symbol.upper()
|
||||
|
||||
# Check if the fiat convertion you want is supported
|
||||
if not self._is_supported_fiat(fiat=fiat_symbol):
|
||||
raise ValueError('The fiat {} is not supported.'.format(fiat_symbol))
|
||||
|
||||
# Get the pair that interest us and return the price in fiat
|
||||
for pair in self._pairs:
|
||||
if pair.crypto_symbol == crypto_symbol and pair.fiat_symbol == fiat_symbol:
|
||||
# If the price is expired we refresh it, avoid to call the API all the time
|
||||
if pair.is_expired():
|
||||
pair.set_price(
|
||||
price=self._find_price(
|
||||
crypto_symbol=pair.crypto_symbol,
|
||||
fiat_symbol=pair.fiat_symbol
|
||||
)
|
||||
)
|
||||
|
||||
# return the last price we have for this pair
|
||||
return pair.price
|
||||
|
||||
# The pair does not exist, so we create it and return the price
|
||||
return self._add_pair(
|
||||
crypto_symbol=crypto_symbol,
|
||||
fiat_symbol=fiat_symbol,
|
||||
price=self._find_price(
|
||||
crypto_symbol=crypto_symbol,
|
||||
fiat_symbol=fiat_symbol
|
||||
)
|
||||
)
|
||||
|
||||
def _add_pair(self, crypto_symbol: str, fiat_symbol: str, price: float) -> float:
|
||||
"""
|
||||
:param crypto_symbol: Crypto-currency you want to convert (e.g BTC)
|
||||
:param fiat_symbol: FIAT currency you want to convert to (e.g USD)
|
||||
:return: price in FIAT
|
||||
"""
|
||||
self._pairs.append(
|
||||
CryptoFiat(
|
||||
crypto_symbol=crypto_symbol,
|
||||
fiat_symbol=fiat_symbol,
|
||||
price=price
|
||||
)
|
||||
)
|
||||
|
||||
return price
|
||||
|
||||
def _is_supported_fiat(self, fiat: str) -> bool:
|
||||
"""
|
||||
Check if the FIAT your want to convert to is supported
|
||||
:param fiat: FIAT to check (e.g USD)
|
||||
:return: bool, True supported, False not supported
|
||||
"""
|
||||
|
||||
fiat = fiat.upper()
|
||||
|
||||
return fiat in self.SUPPORTED_FIAT
|
||||
|
||||
def _find_price(self, crypto_symbol: str, fiat_symbol: str) -> float:
|
||||
"""
|
||||
Call CoinMarketCap API to retrieve the price in the FIAT
|
||||
:param crypto_symbol: Crypto-currency you want to convert (e.g BTC)
|
||||
:param fiat_symbol: FIAT currency you want to convert to (e.g USD)
|
||||
:return: float, price of the crypto-currency in Fiat
|
||||
"""
|
||||
# Check if the fiat convertion you want is supported
|
||||
if not self._is_supported_fiat(fiat=fiat_symbol):
|
||||
raise ValueError('The fiat {} is not supported.'.format(fiat_symbol))
|
||||
|
||||
return float(
|
||||
self._coinmarketcap.ticker(
|
||||
currency=crypto_symbol,
|
||||
convert=fiat_symbol
|
||||
)['price_' + fiat_symbol.lower()]
|
||||
)
|
@ -17,6 +17,7 @@ from freqtrade.analyze import get_signal, SignalType
|
||||
from freqtrade.misc import State, get_state, update_state, parse_args, throttle, \
|
||||
load_config
|
||||
from freqtrade.persistence import Trade
|
||||
from freqtrade.fiat_convert import CryptoToFiatConverter
|
||||
|
||||
logger = logging.getLogger('freqtrade')
|
||||
|
||||
@ -119,14 +120,28 @@ def execute_sell(trade: Trade, limit: float) -> None:
|
||||
trade.open_order_id = order_id
|
||||
|
||||
fmt_exp_profit = round(trade.calc_profit_percent(rate=limit) * 100, 2)
|
||||
rpc.send_msg('*{}:* Selling [{}]({}) with limit `{:.8f} (profit: ~{:.2f}%, {:.8f})`'.format(
|
||||
trade.exchange,
|
||||
trade.pair.replace('_', '/'),
|
||||
exchange.get_pair_detail_url(trade.pair),
|
||||
limit,
|
||||
fmt_exp_profit,
|
||||
trade.calc_profit(rate=limit),
|
||||
))
|
||||
profit_trade = trade.calc_profit(rate=limit)
|
||||
|
||||
fiat_converter = CryptoToFiatConverter()
|
||||
profit_fiat = fiat_converter.convert_amount(
|
||||
profit_trade,
|
||||
_CONF['stake_currency'],
|
||||
_CONF['fiat_display_currency']
|
||||
)
|
||||
|
||||
rpc.send_msg('*{exchange}:* Selling [{pair}]({pair_url}) with limit `{limit:.8f}`'
|
||||
'` (profit: ~{profit_percent:.2f}%, {profit_coin:.8f} {coin}`'
|
||||
'` / {profit_fiat:.3f} {fiat})`'.format(
|
||||
exchange=trade.exchange,
|
||||
pair=trade.pair.replace('_', '/'),
|
||||
pair_url=exchange.get_pair_detail_url(trade.pair),
|
||||
limit=limit,
|
||||
profit_percent=fmt_exp_profit,
|
||||
profit_coin=profit_trade,
|
||||
coin=_CONF['stake_currency'],
|
||||
profit_fiat=profit_fiat,
|
||||
fiat=_CONF['fiat_display_currency'],
|
||||
))
|
||||
Trade.session.flush()
|
||||
|
||||
|
||||
|
@ -208,6 +208,7 @@ CONF_SCHEMA = {
|
||||
'max_open_trades': {'type': 'integer', 'minimum': 1},
|
||||
'stake_currency': {'type': 'string', 'enum': ['BTC', 'ETH', 'USDT']},
|
||||
'stake_amount': {'type': 'number', 'minimum': 0.0005},
|
||||
'fiat_display_currency': {'type': 'string', 'enum': ['USD', 'EUR', 'CAD', 'SGD']},
|
||||
'dry_run': {'type': 'boolean'},
|
||||
'minimal_roi': {
|
||||
'type': 'object',
|
||||
|
@ -15,6 +15,7 @@ from telegram.ext import CommandHandler, Updater
|
||||
from freqtrade import exchange, __version__
|
||||
from freqtrade.misc import get_state, State, update_state
|
||||
from freqtrade.persistence import Trade
|
||||
from freqtrade.fiat_convert import CryptoToFiatConverter
|
||||
|
||||
# Remove noisy log messages
|
||||
logging.getLogger('requests.packages.urllib3').setLevel(logging.INFO)
|
||||
@ -23,6 +24,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
_UPDATER: Updater = None
|
||||
_CONF = {}
|
||||
_FIAT_CONVERT = CryptoToFiatConverter()
|
||||
|
||||
|
||||
def init(config: dict) -> None:
|
||||
@ -242,8 +244,28 @@ def _daily(bot: Bot, update: Update) -> None:
|
||||
curdayprofit = sum(trade.calc_profit() for trade in trades)
|
||||
profit_days[date.fromordinal(today - day)] = format(curdayprofit, '.8f')
|
||||
|
||||
stats = [[key, str(value) + ' BTC'] for key, value in profit_days.items()]
|
||||
stats = tabulate(stats, headers=['Day', 'Profit'], tablefmt='simple')
|
||||
stats = [
|
||||
[
|
||||
key,
|
||||
'{value:.8f} {symbol}'.format(value=float(value), symbol=_CONF['stake_currency']),
|
||||
'{value:.3f} {symbol}'.format(
|
||||
value=_FIAT_CONVERT.convert_amount(
|
||||
value,
|
||||
_CONF['stake_currency'],
|
||||
_CONF['fiat_display_currency']
|
||||
),
|
||||
symbol=_CONF['fiat_display_currency']
|
||||
)
|
||||
]
|
||||
for key, value in profit_days.items()
|
||||
]
|
||||
stats = tabulate(stats,
|
||||
headers=[
|
||||
'Day',
|
||||
'Profit {}'.format(_CONF['stake_currency']),
|
||||
'Profit {}'.format(_CONF['fiat_display_currency'])
|
||||
],
|
||||
tablefmt='simple')
|
||||
|
||||
message = '<b>Daily Profit over the last {} days</b>:\n<pre>{}</pre>'.format(timescale, stats)
|
||||
send_msg(message, bot=bot, parse_mode=ParseMode.HTML)
|
||||
@ -260,9 +282,9 @@ def _profit(bot: Bot, update: Update) -> None:
|
||||
"""
|
||||
trades = Trade.query.order_by(Trade.id).all()
|
||||
|
||||
profit_all_btc = []
|
||||
profit_all_coin = []
|
||||
profit_all_percent = []
|
||||
profit_btc_closed = []
|
||||
profit_closed_coin = []
|
||||
profit_closed_percent = []
|
||||
durations = []
|
||||
|
||||
@ -276,14 +298,14 @@ def _profit(bot: Bot, update: Update) -> None:
|
||||
|
||||
if not trade.is_open:
|
||||
profit_percent = trade.calc_profit_percent()
|
||||
profit_btc_closed.append(trade.calc_profit())
|
||||
profit_closed_coin.append(trade.calc_profit())
|
||||
profit_closed_percent.append(profit_percent)
|
||||
else:
|
||||
# Get current rate
|
||||
current_rate = exchange.get_ticker(trade.pair)['bid']
|
||||
profit_percent = trade.calc_profit_percent(rate=current_rate)
|
||||
|
||||
profit_all_btc.append(trade.calc_profit(rate=Decimal(trade.close_rate or current_rate)))
|
||||
profit_all_coin.append(trade.calc_profit(rate=Decimal(trade.close_rate or current_rate)))
|
||||
profit_all_percent.append(profit_percent)
|
||||
|
||||
best_pair = Trade.session.query(Trade.pair, func.sum(Trade.close_profit).label('profit_sum')) \
|
||||
@ -297,19 +319,46 @@ def _profit(bot: Bot, update: Update) -> None:
|
||||
return
|
||||
|
||||
bp_pair, bp_rate = best_pair
|
||||
|
||||
# Prepare data to display
|
||||
profit_closed_coin = round(sum(profit_closed_coin), 8)
|
||||
profit_closed_percent = round(sum(profit_closed_percent) * 100, 2)
|
||||
profit_closed_fiat = _FIAT_CONVERT.convert_amount(
|
||||
profit_closed_coin,
|
||||
_CONF['stake_currency'],
|
||||
_CONF['fiat_display_currency']
|
||||
)
|
||||
profit_all_coin = round(sum(profit_all_coin), 8)
|
||||
profit_all_percent = round(sum(profit_all_percent) * 100, 2)
|
||||
profit_all_fiat = _FIAT_CONVERT.convert_amount(
|
||||
profit_all_coin,
|
||||
_CONF['stake_currency'],
|
||||
_CONF['fiat_display_currency']
|
||||
)
|
||||
|
||||
# Message to display
|
||||
markdown_msg = """
|
||||
*ROI Trade closed:* `{profit_closed_btc:.8f} BTC ({profit_closed_percent:.2f}%)`
|
||||
*ROI All trades:* `{profit_all_btc:.8f} BTC ({profit_all_percent:.2f}%)`
|
||||
*ROI:* Close trades
|
||||
∙ `{profit_closed_coin:.8f} {coin} ({profit_closed_percent:.2f}%)`
|
||||
∙ `{profit_closed_fiat:.3f} {fiat}`
|
||||
*ROI:* All trades
|
||||
∙ `{profit_all_coin:.8f} {coin} ({profit_all_percent:.2f}%)`
|
||||
∙ `{profit_all_fiat:.3f} {fiat}`
|
||||
|
||||
*Total Trade Count:* `{trade_count}`
|
||||
*First Trade opened:* `{first_trade_date}`
|
||||
*Latest Trade opened:* `{latest_trade_date}`
|
||||
*Avg. Duration:* `{avg_duration}`
|
||||
*Best Performing:* `{best_pair}: {best_rate:.2f}%`
|
||||
""".format(
|
||||
profit_closed_btc=round(sum(profit_btc_closed), 8),
|
||||
profit_closed_percent=round(sum(profit_closed_percent) * 100, 2),
|
||||
profit_all_btc=round(sum(profit_all_btc), 8),
|
||||
profit_all_percent=round(sum(profit_all_percent) * 100, 2),
|
||||
coin=_CONF['stake_currency'],
|
||||
fiat=_CONF['fiat_display_currency'],
|
||||
profit_closed_coin=profit_closed_coin,
|
||||
profit_closed_percent=profit_closed_percent,
|
||||
profit_closed_fiat=profit_closed_fiat,
|
||||
profit_all_coin=profit_all_coin,
|
||||
profit_all_percent=profit_all_percent,
|
||||
profit_all_fiat=profit_all_fiat,
|
||||
trade_count=len(trades),
|
||||
first_trade_date=arrow.get(trades[0].open_date).humanize(),
|
||||
latest_trade_date=arrow.get(trades[-1].open_date).humanize(),
|
||||
|
@ -16,6 +16,7 @@ def default_conf():
|
||||
"max_open_trades": 1,
|
||||
"stake_currency": "BTC",
|
||||
"stake_amount": 0.001,
|
||||
"fiat_display_currency": "USD",
|
||||
"dry_run": True,
|
||||
"minimal_roi": {
|
||||
"40": 0.0,
|
||||
|
111
freqtrade/tests/test_fiat_convert.py
Normal file
111
freqtrade/tests/test_fiat_convert.py
Normal file
@ -0,0 +1,111 @@
|
||||
# pragma pylint: disable=missing-docstring, too-many-arguments, too-many-ancestors, C0103
|
||||
|
||||
import time
|
||||
import pytest
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from freqtrade.fiat_convert import CryptoToFiatConverter, CryptoFiat
|
||||
|
||||
|
||||
def test_pair_convertion_object():
|
||||
pair_convertion = CryptoFiat(
|
||||
crypto_symbol='btc',
|
||||
fiat_symbol='usd',
|
||||
price=12345.0
|
||||
)
|
||||
|
||||
# Check the cache duration is 6 hours
|
||||
assert pair_convertion.CACHE_DURATION == 6 * 60 * 60
|
||||
|
||||
# Check a regular usage
|
||||
assert pair_convertion.crypto_symbol == 'BTC'
|
||||
assert pair_convertion.fiat_symbol == 'USD'
|
||||
assert pair_convertion.price == 12345.0
|
||||
assert pair_convertion.is_expired() is False
|
||||
|
||||
# Update the expiration time (- 2 hours) and check the behavior
|
||||
pair_convertion._expiration = time.time() - 2 * 60 * 60
|
||||
assert pair_convertion.is_expired() is True
|
||||
|
||||
# Check set price behaviour
|
||||
time_reference = time.time() + pair_convertion.CACHE_DURATION
|
||||
pair_convertion.set_price(price=30000.123)
|
||||
assert pair_convertion.is_expired() is False
|
||||
assert pair_convertion._expiration >= time_reference
|
||||
assert pair_convertion.price == 30000.123
|
||||
|
||||
|
||||
def test_fiat_convert_is_supported():
|
||||
fiat_convert = CryptoToFiatConverter()
|
||||
assert fiat_convert._is_supported_fiat(fiat='USD') is True
|
||||
assert fiat_convert._is_supported_fiat(fiat='usd') is True
|
||||
assert fiat_convert._is_supported_fiat(fiat='abc') is False
|
||||
assert fiat_convert._is_supported_fiat(fiat='ABC') is False
|
||||
|
||||
|
||||
def test_fiat_convert_add_pair():
|
||||
fiat_convert = CryptoToFiatConverter()
|
||||
|
||||
assert len(fiat_convert._pairs) == 0
|
||||
|
||||
fiat_convert._add_pair(crypto_symbol='btc', fiat_symbol='usd', price=12345.0)
|
||||
assert len(fiat_convert._pairs) == 1
|
||||
assert fiat_convert._pairs[0].crypto_symbol == 'BTC'
|
||||
assert fiat_convert._pairs[0].fiat_symbol == 'USD'
|
||||
assert fiat_convert._pairs[0].price == 12345.0
|
||||
|
||||
fiat_convert._add_pair(crypto_symbol='btc', fiat_symbol='Eur', price=13000.2)
|
||||
assert len(fiat_convert._pairs) == 2
|
||||
assert fiat_convert._pairs[1].crypto_symbol == 'BTC'
|
||||
assert fiat_convert._pairs[1].fiat_symbol == 'EUR'
|
||||
assert fiat_convert._pairs[1].price == 13000.2
|
||||
|
||||
|
||||
def test_fiat_convert_find_price(mocker):
|
||||
api_mock = MagicMock(return_value={
|
||||
'price_usd': 12345.0,
|
||||
'price_eur': 13000.2
|
||||
})
|
||||
mocker.patch('freqtrade.fiat_convert.Pymarketcap.ticker', api_mock)
|
||||
fiat_convert = CryptoToFiatConverter()
|
||||
|
||||
with pytest.raises(ValueError, match=r'The fiat ABC is not supported.'):
|
||||
fiat_convert._find_price(crypto_symbol='BTC', fiat_symbol='ABC')
|
||||
|
||||
assert fiat_convert.get_price(crypto_symbol='BTC', fiat_symbol='USD') == 12345.0
|
||||
assert fiat_convert.get_price(crypto_symbol='btc', fiat_symbol='usd') == 12345.0
|
||||
assert fiat_convert.get_price(crypto_symbol='BTC', fiat_symbol='EUR') == 13000.2
|
||||
|
||||
|
||||
def test_fiat_convert_get_price(mocker):
|
||||
api_mock = MagicMock(return_value={
|
||||
'price_usd': 28000.0,
|
||||
'price_eur': 15000.0
|
||||
})
|
||||
mocker.patch('freqtrade.fiat_convert.Pymarketcap.ticker', api_mock)
|
||||
|
||||
fiat_convert = CryptoToFiatConverter()
|
||||
|
||||
with pytest.raises(ValueError, match=r'The fiat US DOLLAR is not supported.'):
|
||||
fiat_convert.get_price(crypto_symbol='BTC', fiat_symbol='US Dollar')
|
||||
|
||||
# Check the value return by the method
|
||||
assert len(fiat_convert._pairs) == 0
|
||||
assert fiat_convert.get_price(crypto_symbol='BTC', fiat_symbol='USD') == 28000.0
|
||||
assert fiat_convert._pairs[0].crypto_symbol == 'BTC'
|
||||
assert fiat_convert._pairs[0].fiat_symbol == 'USD'
|
||||
assert fiat_convert._pairs[0].price == 28000.0
|
||||
assert fiat_convert._pairs[0]._expiration is not 0
|
||||
assert len(fiat_convert._pairs) == 1
|
||||
|
||||
# Verify the cached is used
|
||||
fiat_convert._pairs[0].price = 9867.543
|
||||
expiration = fiat_convert._pairs[0]._expiration
|
||||
assert fiat_convert.get_price(crypto_symbol='BTC', fiat_symbol='USD') == 9867.543
|
||||
assert fiat_convert._pairs[0]._expiration == expiration
|
||||
|
||||
# Verify the cache expiration
|
||||
expiration = time.time() - 2 * 60 * 60
|
||||
fiat_convert._pairs[0]._expiration = expiration
|
||||
assert fiat_convert.get_price(crypto_symbol='BTC', fiat_symbol='USD') == 28000.0
|
||||
assert fiat_convert._pairs[0]._expiration is not expiration
|
@ -192,6 +192,9 @@ def test_handle_trade(default_conf, limit_buy_order, limit_sell_order, mocker):
|
||||
}),
|
||||
buy=MagicMock(return_value='mocked_limit_buy'),
|
||||
sell=MagicMock(return_value='mocked_limit_sell'))
|
||||
mocker.patch.multiple('freqtrade.fiat_convert.Pymarketcap',
|
||||
ticker=MagicMock(return_value={'price_usd': 15000.0}),
|
||||
_cache_symbols=MagicMock(return_value={'BTC': 1}))
|
||||
init(default_conf, create_engine('sqlite://'))
|
||||
create_trade(0.001)
|
||||
|
||||
|
@ -164,6 +164,9 @@ def test_profit_handle(
|
||||
mocker.patch.multiple('freqtrade.main.exchange',
|
||||
validate_pairs=MagicMock(),
|
||||
get_ticker=ticker)
|
||||
mocker.patch.multiple('freqtrade.fiat_convert.Pymarketcap',
|
||||
ticker=MagicMock(return_value={'price_usd': 15000.0}),
|
||||
_cache_symbols=MagicMock(return_value={'BTC': 1}))
|
||||
init(default_conf, create_engine('sqlite://'))
|
||||
|
||||
_profit(bot=MagicMock(), update=update)
|
||||
@ -194,9 +197,14 @@ def test_profit_handle(
|
||||
|
||||
_profit(bot=MagicMock(), update=update)
|
||||
assert msg_mock.call_count == 1
|
||||
assert '*ROI Trade closed:* `0.00006217 BTC (6.20%)`' in msg_mock.call_args_list[-1][0][0]
|
||||
assert '*ROI All trades:* `0.00006217 BTC (6.20%)`' in msg_mock.call_args_list[-1][0][0]
|
||||
assert 'Best Performing:* `BTC_ETH: 6.20%`' in msg_mock.call_args_list[-1][0][0]
|
||||
assert '*ROI:* Close trades' in msg_mock.call_args_list[-1][0][0]
|
||||
assert '∙ `0.00006217 BTC (6.20%)`' in msg_mock.call_args_list[-1][0][0]
|
||||
assert '∙ `0.933 USD`' in msg_mock.call_args_list[-1][0][0]
|
||||
assert '*ROI:* All trades' in msg_mock.call_args_list[-1][0][0]
|
||||
assert '∙ `0.00006217 BTC (6.20%)`' in msg_mock.call_args_list[-1][0][0]
|
||||
assert '∙ `0.933 USD`' in msg_mock.call_args_list[-1][0][0]
|
||||
|
||||
assert '*Best Performing:* `BTC_ETH: 6.20%`' in msg_mock.call_args_list[-1][0][0]
|
||||
|
||||
|
||||
def test_forcesell_handle(default_conf, update, ticker, ticker_sell_up, mocker):
|
||||
@ -210,6 +218,9 @@ def test_forcesell_handle(default_conf, update, ticker, ticker_sell_up, mocker):
|
||||
mocker.patch.multiple('freqtrade.main.exchange',
|
||||
validate_pairs=MagicMock(),
|
||||
get_ticker=ticker)
|
||||
mocker.patch.multiple('freqtrade.fiat_convert.Pymarketcap',
|
||||
ticker=MagicMock(return_value={'price_usd': 15000.0}),
|
||||
_cache_symbols=MagicMock(return_value={'BTC': 1}))
|
||||
init(default_conf, create_engine('sqlite://'))
|
||||
|
||||
# Create some test data
|
||||
@ -228,7 +239,9 @@ def test_forcesell_handle(default_conf, update, ticker, ticker_sell_up, mocker):
|
||||
|
||||
assert rpc_mock.call_count == 2
|
||||
assert 'Selling [BTC/ETH]' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert '0.00001172 (profit: ~6.11%, 0.00006126)' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert '0.00001172' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert 'profit: ~6.11%, 0.00006126' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert '0.919 USD' in rpc_mock.call_args_list[-1][0][0]
|
||||
|
||||
|
||||
def test_forcesell_down_handle(default_conf, update, ticker, ticker_sell_down, mocker):
|
||||
@ -242,6 +255,9 @@ def test_forcesell_down_handle(default_conf, update, ticker, ticker_sell_down, m
|
||||
mocker.patch.multiple('freqtrade.main.exchange',
|
||||
validate_pairs=MagicMock(),
|
||||
get_ticker=ticker)
|
||||
mocker.patch.multiple('freqtrade.fiat_convert.Pymarketcap',
|
||||
ticker=MagicMock(return_value={'price_usd': 15000.0}),
|
||||
_cache_symbols=MagicMock(return_value={'BTC': 1}))
|
||||
init(default_conf, create_engine('sqlite://'))
|
||||
|
||||
# Create some test data
|
||||
@ -260,7 +276,9 @@ def test_forcesell_down_handle(default_conf, update, ticker, ticker_sell_down, m
|
||||
|
||||
assert rpc_mock.call_count == 2
|
||||
assert 'Selling [BTC/ETH]' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert '0.00001044 (profit: ~-5.48%, -0.00005492)' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert '0.00001044' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert 'profit: ~-5.48%, -0.00005492' in rpc_mock.call_args_list[-1][0][0]
|
||||
assert '-0.824 USD' in rpc_mock.call_args_list[-1][0][0]
|
||||
|
||||
|
||||
def test_exec_forcesell_open_orders(default_conf, ticker, mocker):
|
||||
@ -298,6 +316,9 @@ def test_forcesell_all_handle(default_conf, update, ticker, mocker):
|
||||
mocker.patch.multiple('freqtrade.main.exchange',
|
||||
validate_pairs=MagicMock(),
|
||||
get_ticker=ticker)
|
||||
mocker.patch.multiple('freqtrade.fiat_convert.Pymarketcap',
|
||||
ticker=MagicMock(return_value={'price_usd': 15000.0}),
|
||||
_cache_symbols=MagicMock(return_value={'BTC': 1}))
|
||||
init(default_conf, create_engine('sqlite://'))
|
||||
|
||||
# Create some test data
|
||||
@ -310,7 +331,9 @@ def test_forcesell_all_handle(default_conf, update, ticker, mocker):
|
||||
|
||||
assert rpc_mock.call_count == 4
|
||||
for args in rpc_mock.call_args_list:
|
||||
assert '0.00001098 (profit: ~-0.59%, -0.00000591)' in args[0][0]
|
||||
assert '0.00001098' in args[0][0]
|
||||
assert 'profit: ~-0.59%, -0.00000591 BTC' in args[0][0]
|
||||
assert '-0.089 USD' in args[0][0]
|
||||
|
||||
|
||||
def test_forcesell_handle_invalid(default_conf, update, mocker):
|
||||
@ -397,6 +420,9 @@ def test_daily_handle(
|
||||
mocker.patch.multiple('freqtrade.main.exchange',
|
||||
validate_pairs=MagicMock(),
|
||||
get_ticker=ticker)
|
||||
mocker.patch.multiple('freqtrade.fiat_convert.Pymarketcap',
|
||||
ticker=MagicMock(return_value={'price_usd': 15000.0}),
|
||||
_cache_symbols=MagicMock(return_value={'BTC': 1}))
|
||||
init(default_conf, create_engine('sqlite://'))
|
||||
|
||||
# Create some test data
|
||||
@ -418,7 +444,9 @@ def test_daily_handle(
|
||||
_daily(bot=MagicMock(), update=update)
|
||||
assert msg_mock.call_count == 1
|
||||
assert 'Daily' in msg_mock.call_args_list[0][0][0]
|
||||
assert str(datetime.utcnow().date()) + ' 0.00006217 BTC' in msg_mock.call_args_list[0][0][0]
|
||||
assert str(datetime.utcnow().date()) in msg_mock.call_args_list[0][0][0]
|
||||
assert str(' 0.00006217 BTC') in msg_mock.call_args_list[0][0][0]
|
||||
assert str(' 0.933 USD') in msg_mock.call_args_list[0][0][0]
|
||||
|
||||
# Try invalid data
|
||||
msg_mock.reset_mock()
|
||||
|
@ -19,6 +19,7 @@ hyperopt==0.1
|
||||
# do not upgrade networkx before this is fixed https://github.com/hyperopt/hyperopt/issues/325
|
||||
networkx==1.11
|
||||
tabulate==0.8.2
|
||||
pymarketcap==3.3.139
|
||||
|
||||
# Required for plotting data
|
||||
#matplotlib==2.1.0
|
||||
|
Loading…
Reference in New Issue
Block a user