Fix the fee calculation
This commit is contained in:
parent
642422d5c4
commit
d613d63fdc
@ -51,7 +51,7 @@ class Bittrex(Exchange):
|
|||||||
@property
|
@property
|
||||||
def fee(self) -> float:
|
def fee(self) -> float:
|
||||||
# See https://bittrex.com/fees
|
# See https://bittrex.com/fees
|
||||||
return 0.0025
|
return 0.0025 #0.25%
|
||||||
|
|
||||||
def buy(self, pair: str, rate: float, amount: float) -> str:
|
def buy(self, pair: str, rate: float, amount: float) -> str:
|
||||||
data = _API.buy_limit(pair.replace('_', '-'), amount, rate)
|
data = _API.buy_limit(pair.replace('_', '-'), amount, rate)
|
||||||
|
@ -118,13 +118,14 @@ def execute_sell(trade: Trade, limit: float) -> None:
|
|||||||
order_id = exchange.sell(str(trade.pair), limit, trade.amount)
|
order_id = exchange.sell(str(trade.pair), limit, trade.amount)
|
||||||
trade.open_order_id = order_id
|
trade.open_order_id = order_id
|
||||||
|
|
||||||
fmt_exp_profit = round(trade.calc_profit(limit) * 100, 2)
|
fmt_exp_profit = round(trade.calc_profit_percent(rate=limit) * 100, 2)
|
||||||
rpc.send_msg('*{}:* Selling [{}]({}) with limit `{:.8f} (profit: ~{:.2f}%)`'.format(
|
rpc.send_msg('*{}:* Selling [{}]({}) with limit `{:.8f} (profit: ~{:.2f}%, {:.8f})`'.format(
|
||||||
trade.exchange,
|
trade.exchange,
|
||||||
trade.pair.replace('_', '/'),
|
trade.pair.replace('_', '/'),
|
||||||
exchange.get_pair_detail_url(trade.pair),
|
exchange.get_pair_detail_url(trade.pair),
|
||||||
limit,
|
limit,
|
||||||
fmt_exp_profit
|
fmt_exp_profit,
|
||||||
|
trade.calc_profit(rate=limit),
|
||||||
))
|
))
|
||||||
Trade.session.flush()
|
Trade.session.flush()
|
||||||
|
|
||||||
@ -134,7 +135,7 @@ def min_roi_reached(trade: Trade, current_rate: float, current_time: datetime) -
|
|||||||
Based an earlier trade and current price and ROI configuration, decides whether bot should sell
|
Based an earlier trade and current price and ROI configuration, decides whether bot should sell
|
||||||
:return True if bot should sell at current rate
|
:return True if bot should sell at current rate
|
||||||
"""
|
"""
|
||||||
current_profit = trade.calc_profit(current_rate)
|
current_profit = trade.calc_profit_percent(current_rate)
|
||||||
if 'stoploss' in _CONF and current_profit < float(_CONF['stoploss']):
|
if 'stoploss' in _CONF and current_profit < float(_CONF['stoploss']):
|
||||||
logger.debug('Stop loss hit.')
|
logger.debug('Stop loss hit.')
|
||||||
return True
|
return True
|
||||||
@ -145,7 +146,7 @@ def min_roi_reached(trade: Trade, current_rate: float, current_time: datetime) -
|
|||||||
if time_diff > float(duration) and current_profit > threshold:
|
if time_diff > float(duration) and current_profit > threshold:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
logger.debug('Threshold not reached. (cur_profit: %1.2f%%)', current_profit * 100.0)
|
logger.debug('Threshold not reached. (cur_profit: %1.2f%%)', float(current_profit) * 100.0)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@ -233,7 +234,7 @@ def create_trade(stake_amount: float) -> bool:
|
|||||||
pair=pair,
|
pair=pair,
|
||||||
stake_amount=stake_amount,
|
stake_amount=stake_amount,
|
||||||
amount=amount,
|
amount=amount,
|
||||||
fee=exchange.get_fee() * 2,
|
fee=exchange.get_fee(),
|
||||||
open_rate=buy_limit,
|
open_rate=buy_limit,
|
||||||
open_date=datetime.utcnow(),
|
open_date=datetime.utcnow(),
|
||||||
exchange=exchange.get_name().upper(),
|
exchange=exchange.get_name().upper(),
|
||||||
|
@ -99,7 +99,7 @@ def backtest(config: Dict, processed: Dict[str, DataFrame],
|
|||||||
open_rate=row.close,
|
open_rate=row.close,
|
||||||
open_date=row.date,
|
open_date=row.date,
|
||||||
amount=config['stake_amount'],
|
amount=config['stake_amount'],
|
||||||
fee=exchange.get_fee() * 2
|
fee=exchange.get_fee()
|
||||||
)
|
)
|
||||||
|
|
||||||
# calculate win/lose forwards from buy point
|
# calculate win/lose forwards from buy point
|
||||||
@ -109,7 +109,7 @@ def backtest(config: Dict, processed: Dict[str, DataFrame],
|
|||||||
trade_count_lock[row2.date] = trade_count_lock.get(row2.date, 0) + 1
|
trade_count_lock[row2.date] = trade_count_lock.get(row2.date, 0) + 1
|
||||||
|
|
||||||
if min_roi_reached(trade, row2.close, row2.date) or row2.sell == 1:
|
if min_roi_reached(trade, row2.close, row2.date) or row2.sell == 1:
|
||||||
current_profit = trade.calc_profit(row2.close)
|
current_profit = trade.calc_profit_percent(row2.close)
|
||||||
lock_pair_until = row2.Index
|
lock_pair_until = row2.Index
|
||||||
|
|
||||||
trades.append((pair, current_profit, row2.Index - row.Index))
|
trades.append((pair, current_profit, row2.Index - row.Index))
|
||||||
|
@ -92,10 +92,12 @@ class Trade(_DECL_BASE):
|
|||||||
return
|
return
|
||||||
|
|
||||||
logger.info('Updating trade (id=%d) ...', self.id)
|
logger.info('Updating trade (id=%d) ...', self.id)
|
||||||
|
|
||||||
|
getcontext().prec = 8 # Bittrex do not go above 8 decimal
|
||||||
if order['type'] == 'LIMIT_BUY':
|
if order['type'] == 'LIMIT_BUY':
|
||||||
# Update open rate and actual amount
|
# Update open rate and actual amount
|
||||||
self.open_rate = order['rate']
|
self.open_rate = Decimal(order['rate'])
|
||||||
self.amount = order['amount']
|
self.amount = Decimal(order['amount'])
|
||||||
logger.info('LIMIT_BUY has been fulfilled for %s.', self)
|
logger.info('LIMIT_BUY has been fulfilled for %s.', self)
|
||||||
self.open_order_id = None
|
self.open_order_id = None
|
||||||
elif order['type'] == 'LIMIT_SELL':
|
elif order['type'] == 'LIMIT_SELL':
|
||||||
@ -109,8 +111,8 @@ class Trade(_DECL_BASE):
|
|||||||
Sets close_rate to the given rate, calculates total profit
|
Sets close_rate to the given rate, calculates total profit
|
||||||
and marks trade as closed
|
and marks trade as closed
|
||||||
"""
|
"""
|
||||||
self.close_rate = rate
|
self.close_rate = Decimal(rate)
|
||||||
self.close_profit = self.calc_profit()
|
self.close_profit = self.calc_profit_percent()
|
||||||
self.close_date = datetime.utcnow()
|
self.close_date = datetime.utcnow()
|
||||||
self.is_open = False
|
self.is_open = False
|
||||||
self.open_order_id = None
|
self.open_order_id = None
|
||||||
@ -119,7 +121,54 @@ class Trade(_DECL_BASE):
|
|||||||
self
|
self
|
||||||
)
|
)
|
||||||
|
|
||||||
def calc_profit(self, rate: Optional[float] = None) -> float:
|
def calc_open_trade_price(self, fee: Optional[float] = None) -> float:
|
||||||
|
"""
|
||||||
|
Calculate the open_rate in BTC
|
||||||
|
:param fee: fee to use on the open rate (optional).
|
||||||
|
If rate is not set self.fee will be used
|
||||||
|
:return: Price in BTC of the open trade
|
||||||
|
"""
|
||||||
|
getcontext().prec = 8
|
||||||
|
|
||||||
|
buy_trade = (Decimal(self.amount) * Decimal(self.open_rate))
|
||||||
|
fees = buy_trade * Decimal(fee or self.fee)
|
||||||
|
return float(buy_trade + fees)
|
||||||
|
|
||||||
|
def calc_close_trade_price(self, rate: Optional[float] = None, fee: Optional[float] = None) -> float:
|
||||||
|
"""
|
||||||
|
Calculate the close_rate in BTC
|
||||||
|
:param fee: fee to use on the close rate (optional).
|
||||||
|
If rate is not set self.fee will be used
|
||||||
|
:param rate: rate to compare with (optional).
|
||||||
|
If rate is not set self.close_rate will be used
|
||||||
|
:return: Price in BTC of the open trade
|
||||||
|
"""
|
||||||
|
getcontext().prec = 8
|
||||||
|
|
||||||
|
if rate is None and not self.close_rate:
|
||||||
|
return 0.0
|
||||||
|
|
||||||
|
sell_trade = (Decimal(self.amount) * Decimal(rate or self.close_rate))
|
||||||
|
fees = sell_trade * Decimal(fee or self.fee)
|
||||||
|
return float(sell_trade - fees)
|
||||||
|
|
||||||
|
def calc_profit(self, rate: Optional[float] = None, fee: Optional[float] = None) -> float:
|
||||||
|
"""
|
||||||
|
Calculate the profit in BTC between Close and Open trade
|
||||||
|
:param fee: fee to use on the close rate (optional).
|
||||||
|
If rate is not set self.fee will be used
|
||||||
|
:param rate: close rate to compare with (optional).
|
||||||
|
If rate is not set self.close_rate will be used
|
||||||
|
:return: profit in BTC as float
|
||||||
|
"""
|
||||||
|
open_trade_price = self.calc_open_trade_price()
|
||||||
|
close_trade_price = self.calc_close_trade_price(
|
||||||
|
rate=Decimal(rate or self.close_rate),
|
||||||
|
fee=Decimal(fee or self.fee)
|
||||||
|
)
|
||||||
|
return float("{0:.8f}".format(close_trade_price - open_trade_price))
|
||||||
|
|
||||||
|
def calc_profit_percent(self, rate: Optional[float] = None, fee: Optional[float] = None) -> float:
|
||||||
"""
|
"""
|
||||||
Calculates the profit in percentage (including fee).
|
Calculates the profit in percentage (including fee).
|
||||||
:param rate: rate to compare with (optional).
|
:param rate: rate to compare with (optional).
|
||||||
@ -127,5 +176,11 @@ class Trade(_DECL_BASE):
|
|||||||
:return: profit in percentage as float
|
:return: profit in percentage as float
|
||||||
"""
|
"""
|
||||||
getcontext().prec = 8
|
getcontext().prec = 8
|
||||||
return float((Decimal(rate or self.close_rate) - Decimal(self.open_rate))
|
|
||||||
/ Decimal(self.open_rate) - Decimal(self.fee))
|
open_trade_price = self.calc_open_trade_price()
|
||||||
|
close_trade_price = self.calc_close_trade_price(
|
||||||
|
rate=Decimal(rate or self.close_rate),
|
||||||
|
fee=Decimal(fee or self.fee)
|
||||||
|
)
|
||||||
|
|
||||||
|
return float("{0:.8f}".format((close_trade_price / open_trade_price) - 1))
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
from datetime import timedelta, date
|
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
from datetime import timedelta, date, datetime
|
||||||
from typing import Callable, Any
|
from typing import Callable, Any
|
||||||
|
|
||||||
import arrow
|
import arrow
|
||||||
@ -139,7 +139,7 @@ def _status(bot: Bot, update: Update) -> None:
|
|||||||
order = exchange.get_order(trade.open_order_id)
|
order = exchange.get_order(trade.open_order_id)
|
||||||
# calculate profit and send message to user
|
# calculate profit and send message to user
|
||||||
current_rate = exchange.get_ticker(trade.pair)['bid']
|
current_rate = exchange.get_ticker(trade.pair)['bid']
|
||||||
current_profit = trade.calc_profit(current_rate)
|
current_profit = trade.calc_profit_percent(current_rate)
|
||||||
fmt_close_profit = '{:.2f}%'.format(
|
fmt_close_profit = '{:.2f}%'.format(
|
||||||
round(trade.close_profit * 100, 2)
|
round(trade.close_profit * 100, 2)
|
||||||
) if trade.close_profit else None
|
) if trade.close_profit else None
|
||||||
@ -196,7 +196,7 @@ def _status_table(bot: Bot, update: Update) -> None:
|
|||||||
trade.id,
|
trade.id,
|
||||||
trade.pair,
|
trade.pair,
|
||||||
shorten_date(arrow.get(trade.open_date).humanize(only_distance=True)),
|
shorten_date(arrow.get(trade.open_date).humanize(only_distance=True)),
|
||||||
'{:.2f}'.format(100 * trade.calc_profit(current_rate))
|
'{:.2f}'.format(100 * trade.calc_profit_percent(current_rate))
|
||||||
])
|
])
|
||||||
|
|
||||||
columns = ['ID', 'Pair', 'Since', 'Profit']
|
columns = ['ID', 'Pair', 'Since', 'Profit']
|
||||||
@ -218,7 +218,7 @@ def _daily(bot: Bot, update: Update) -> None:
|
|||||||
:param update: message update
|
:param update: message update
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
today = date.today().toordinal()
|
today = datetime.utcnow().toordinal()
|
||||||
profit_days = {}
|
profit_days = {}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -234,9 +234,13 @@ def _daily(bot: Bot, update: Update) -> None:
|
|||||||
# need to query between day+1 and day-1
|
# need to query between day+1 and day-1
|
||||||
nextdate = date.fromordinal(today-day+1)
|
nextdate = date.fromordinal(today-day+1)
|
||||||
prevdate = date.fromordinal(today-day-1)
|
prevdate = date.fromordinal(today-day-1)
|
||||||
trades = Trade.query.filter(between(Trade.close_date, prevdate, nextdate)).all()
|
trades = Trade.query \
|
||||||
curdayprofit = sum(trade.close_profit * trade.stake_amount for trade in trades)
|
.filter(Trade.is_open.is_(False)) \
|
||||||
profit_days[date.fromordinal(today-day)] = format(curdayprofit, '.8f')
|
.filter(between(Trade.close_date, prevdate, nextdate)) \
|
||||||
|
.order_by(Trade.close_date)\
|
||||||
|
.all()
|
||||||
|
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 = [[key, str(value) + ' BTC'] for key, value in profit_days.items()]
|
||||||
stats = tabulate(stats, headers=['Day', 'Profit'], tablefmt='simple')
|
stats = tabulate(stats, headers=['Day', 'Profit'], tablefmt='simple')
|
||||||
@ -257,9 +261,9 @@ def _profit(bot: Bot, update: Update) -> None:
|
|||||||
trades = Trade.query.order_by(Trade.id).all()
|
trades = Trade.query.order_by(Trade.id).all()
|
||||||
|
|
||||||
profit_all_btc = []
|
profit_all_btc = []
|
||||||
profit_all = []
|
profit_all_percent = []
|
||||||
profit_btc_closed = []
|
profit_btc_closed = []
|
||||||
profit_closed = []
|
profit_closed_percent = []
|
||||||
durations = []
|
durations = []
|
||||||
|
|
||||||
for trade in trades:
|
for trade in trades:
|
||||||
@ -271,16 +275,16 @@ def _profit(bot: Bot, update: Update) -> None:
|
|||||||
durations.append((trade.close_date - trade.open_date).total_seconds())
|
durations.append((trade.close_date - trade.open_date).total_seconds())
|
||||||
|
|
||||||
if not trade.is_open:
|
if not trade.is_open:
|
||||||
profit = trade.close_profit
|
profit_percent = trade.calc_profit_percent()
|
||||||
profit_btc_closed.append(Decimal(trade.close_rate) - Decimal(trade.open_rate))
|
profit_btc_closed.append(trade.calc_profit())
|
||||||
profit_closed.append(profit)
|
profit_closed_percent.append(profit_percent)
|
||||||
else:
|
else:
|
||||||
# Get current rate
|
# Get current rate
|
||||||
current_rate = exchange.get_ticker(trade.pair)['bid']
|
current_rate = exchange.get_ticker(trade.pair)['bid']
|
||||||
profit = trade.calc_profit(current_rate)
|
profit_percent = trade.calc_profit_percent(rate=current_rate)
|
||||||
|
|
||||||
profit_all_btc.append(Decimal(trade.close_rate or current_rate) - Decimal(trade.open_rate))
|
profit_all_btc.append(trade.calc_profit(rate=Decimal(trade.close_rate or current_rate)))
|
||||||
profit_all.append(profit)
|
profit_all_percent.append(profit_percent)
|
||||||
|
|
||||||
best_pair = Trade.session.query(Trade.pair, func.sum(Trade.close_profit).label('profit_sum')) \
|
best_pair = Trade.session.query(Trade.pair, func.sum(Trade.close_profit).label('profit_sum')) \
|
||||||
.filter(Trade.is_open.is_(False)) \
|
.filter(Trade.is_open.is_(False)) \
|
||||||
@ -294,8 +298,8 @@ def _profit(bot: Bot, update: Update) -> None:
|
|||||||
|
|
||||||
bp_pair, bp_rate = best_pair
|
bp_pair, bp_rate = best_pair
|
||||||
markdown_msg = """
|
markdown_msg = """
|
||||||
*ROI Trade closed:* `{profit_closed_btc:.8f} BTC ({profit_closed:.2f}%)`
|
*ROI Trade closed:* `{profit_closed_btc:.8f} BTC ({profit_closed_percent:.2f}%)`
|
||||||
*ROI All trades:* `{profit_all_btc:.8f} BTC ({profit_all:.2f}%)`
|
*ROI All trades:* `{profit_all_btc:.8f} BTC ({profit_all_percent:.2f}%)`
|
||||||
*Total Trade Count:* `{trade_count}`
|
*Total Trade Count:* `{trade_count}`
|
||||||
*First Trade opened:* `{first_trade_date}`
|
*First Trade opened:* `{first_trade_date}`
|
||||||
*Latest Trade opened:* `{latest_trade_date}`
|
*Latest Trade opened:* `{latest_trade_date}`
|
||||||
@ -303,9 +307,9 @@ def _profit(bot: Bot, update: Update) -> None:
|
|||||||
*Best Performing:* `{best_pair}: {best_rate:.2f}%`
|
*Best Performing:* `{best_pair}: {best_rate:.2f}%`
|
||||||
""".format(
|
""".format(
|
||||||
profit_closed_btc=round(sum(profit_btc_closed), 8),
|
profit_closed_btc=round(sum(profit_btc_closed), 8),
|
||||||
profit_closed=round(sum(profit_closed) * 100, 2),
|
profit_closed_percent=round(sum(profit_closed_percent) * 100, 2),
|
||||||
profit_all_btc=round(sum(profit_all_btc), 8),
|
profit_all_btc=round(sum(profit_all_btc), 8),
|
||||||
profit_all=round(sum(profit_all) * 100, 2),
|
profit_all_percent=round(sum(profit_all_percent) * 100, 2),
|
||||||
trade_count=len(trades),
|
trade_count=len(trades),
|
||||||
first_trade_date=arrow.get(trades[0].open_date).humanize(),
|
first_trade_date=arrow.get(trades[0].open_date).humanize(),
|
||||||
latest_trade_date=arrow.get(trades[-1].open_date).humanize(),
|
latest_trade_date=arrow.get(trades[-1].open_date).humanize(),
|
||||||
|
@ -15,7 +15,7 @@ def default_conf():
|
|||||||
configuration = {
|
configuration = {
|
||||||
"max_open_trades": 1,
|
"max_open_trades": 1,
|
||||||
"stake_currency": "BTC",
|
"stake_currency": "BTC",
|
||||||
"stake_amount": 0.05,
|
"stake_amount": 0.001,
|
||||||
"dry_run": True,
|
"dry_run": True,
|
||||||
"minimal_roi": {
|
"minimal_roi": {
|
||||||
"40": 0.0,
|
"40": 0.0,
|
||||||
@ -61,11 +61,26 @@ def update():
|
|||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def ticker():
|
def ticker():
|
||||||
return MagicMock(return_value={
|
return MagicMock(return_value={
|
||||||
'bid': 0.07256061,
|
'bid': 0.00001098,
|
||||||
'ask': 0.072661,
|
'ask': 0.00001099,
|
||||||
'last': 0.07256061,
|
'last': 0.00001098,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def ticker_sell_up():
|
||||||
|
return MagicMock(return_value={
|
||||||
|
'bid': 0.00001172,
|
||||||
|
'ask': 0.00001173,
|
||||||
|
'last': 0.00001172,
|
||||||
|
})
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def ticker_sell_down():
|
||||||
|
return MagicMock(return_value={
|
||||||
|
'bid': 0.00001044,
|
||||||
|
'ask': 0.00001043,
|
||||||
|
'last': 0.00001044,
|
||||||
|
})
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def health():
|
def health():
|
||||||
@ -104,8 +119,8 @@ def limit_buy_order():
|
|||||||
'type': 'LIMIT_BUY',
|
'type': 'LIMIT_BUY',
|
||||||
'pair': 'mocked',
|
'pair': 'mocked',
|
||||||
'opened': datetime.utcnow(),
|
'opened': datetime.utcnow(),
|
||||||
'rate': 0.07256061,
|
'rate': 0.00001099,
|
||||||
'amount': 206.43811673387373,
|
'amount': 90.99181073,
|
||||||
'remaining': 0.0,
|
'remaining': 0.0,
|
||||||
'closed': datetime.utcnow(),
|
'closed': datetime.utcnow(),
|
||||||
}
|
}
|
||||||
@ -118,8 +133,8 @@ def limit_sell_order():
|
|||||||
'type': 'LIMIT_SELL',
|
'type': 'LIMIT_SELL',
|
||||||
'pair': 'mocked',
|
'pair': 'mocked',
|
||||||
'opened': datetime.utcnow(),
|
'opened': datetime.utcnow(),
|
||||||
'rate': 0.0802134,
|
'rate': 0.00001173,
|
||||||
'amount': 206.43811673387373,
|
'amount': 90.99181073,
|
||||||
'remaining': 0.0,
|
'remaining': 0.0,
|
||||||
'closed': datetime.utcnow(),
|
'closed': datetime.utcnow(),
|
||||||
}
|
}
|
||||||
@ -155,4 +170,4 @@ def ticker_history():
|
|||||||
"T": "2017-11-26T09:00:00",
|
"T": "2017-11-26T09:00:00",
|
||||||
"BV": 0.7039405
|
"BV": 0.7039405
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -40,8 +40,8 @@ def test_process_trade_creation(default_conf, ticker, health, mocker):
|
|||||||
assert trade.is_open
|
assert trade.is_open
|
||||||
assert trade.open_date is not None
|
assert trade.open_date is not None
|
||||||
assert trade.exchange == Exchanges.BITTREX.name
|
assert trade.exchange == Exchanges.BITTREX.name
|
||||||
assert trade.open_rate == 0.072661
|
assert trade.open_rate == 0.00001099
|
||||||
assert trade.amount == 0.6881270557795791
|
assert trade.amount == 90.99181073703367
|
||||||
|
|
||||||
|
|
||||||
def test_process_exchange_failures(default_conf, ticker, health, mocker):
|
def test_process_exchange_failures(default_conf, ticker, health, mocker):
|
||||||
@ -115,11 +115,11 @@ def test_create_trade(default_conf, ticker, limit_buy_order, mocker):
|
|||||||
whitelist = copy.deepcopy(default_conf['exchange']['pair_whitelist'])
|
whitelist = copy.deepcopy(default_conf['exchange']['pair_whitelist'])
|
||||||
|
|
||||||
init(default_conf, create_engine('sqlite://'))
|
init(default_conf, create_engine('sqlite://'))
|
||||||
create_trade(15.0)
|
create_trade(0.001)
|
||||||
|
|
||||||
trade = Trade.query.first()
|
trade = Trade.query.first()
|
||||||
assert trade is not None
|
assert trade is not None
|
||||||
assert trade.stake_amount == 15.0
|
assert trade.stake_amount == 0.001
|
||||||
assert trade.is_open
|
assert trade.is_open
|
||||||
assert trade.open_date is not None
|
assert trade.open_date is not None
|
||||||
assert trade.exchange == Exchanges.BITTREX.name
|
assert trade.exchange == Exchanges.BITTREX.name
|
||||||
@ -127,8 +127,8 @@ def test_create_trade(default_conf, ticker, limit_buy_order, mocker):
|
|||||||
# Simulate fulfilled LIMIT_BUY order for trade
|
# Simulate fulfilled LIMIT_BUY order for trade
|
||||||
trade.update(limit_buy_order)
|
trade.update(limit_buy_order)
|
||||||
|
|
||||||
assert trade.open_rate == 0.07256061
|
assert trade.open_rate == 0.00001099
|
||||||
assert trade.amount == 206.43811673387373
|
assert trade.amount == 90.99181073
|
||||||
|
|
||||||
assert whitelist == default_conf['exchange']['pair_whitelist']
|
assert whitelist == default_conf['exchange']['pair_whitelist']
|
||||||
|
|
||||||
@ -186,14 +186,14 @@ def test_handle_trade(default_conf, limit_buy_order, limit_sell_order, mocker):
|
|||||||
mocker.patch.multiple('freqtrade.main.exchange',
|
mocker.patch.multiple('freqtrade.main.exchange',
|
||||||
validate_pairs=MagicMock(),
|
validate_pairs=MagicMock(),
|
||||||
get_ticker=MagicMock(return_value={
|
get_ticker=MagicMock(return_value={
|
||||||
'bid': 0.17256061,
|
'bid': 0.00001172,
|
||||||
'ask': 0.172661,
|
'ask': 0.00001173,
|
||||||
'last': 0.17256061
|
'last': 0.00001172
|
||||||
}),
|
}),
|
||||||
buy=MagicMock(return_value='mocked_limit_buy'),
|
buy=MagicMock(return_value='mocked_limit_buy'),
|
||||||
sell=MagicMock(return_value='mocked_limit_sell'))
|
sell=MagicMock(return_value='mocked_limit_sell'))
|
||||||
init(default_conf, create_engine('sqlite://'))
|
init(default_conf, create_engine('sqlite://'))
|
||||||
create_trade(15.0)
|
create_trade(0.001)
|
||||||
|
|
||||||
trade = Trade.query.first()
|
trade = Trade.query.first()
|
||||||
assert trade
|
assert trade
|
||||||
@ -207,8 +207,9 @@ def test_handle_trade(default_conf, limit_buy_order, limit_sell_order, mocker):
|
|||||||
# Simulate fulfilled LIMIT_SELL order for trade
|
# Simulate fulfilled LIMIT_SELL order for trade
|
||||||
trade.update(limit_sell_order)
|
trade.update(limit_sell_order)
|
||||||
|
|
||||||
assert trade.close_rate == 0.0802134
|
assert trade.close_rate == 0.00001173
|
||||||
assert trade.close_profit == 0.10046755
|
assert trade.close_profit == 0.06201057
|
||||||
|
assert trade.calc_profit() == 0.00006217
|
||||||
assert trade.close_date is not None
|
assert trade.close_date is not None
|
||||||
|
|
||||||
|
|
||||||
@ -223,7 +224,7 @@ def test_close_trade(default_conf, ticker, limit_buy_order, limit_sell_order, mo
|
|||||||
|
|
||||||
# Create trade and sell it
|
# Create trade and sell it
|
||||||
init(default_conf, create_engine('sqlite://'))
|
init(default_conf, create_engine('sqlite://'))
|
||||||
create_trade(15.0)
|
create_trade(0.001)
|
||||||
|
|
||||||
trade = Trade.query.first()
|
trade = Trade.query.first()
|
||||||
assert trade
|
assert trade
|
||||||
|
@ -5,11 +5,32 @@ from freqtrade.exchange import Exchanges
|
|||||||
from freqtrade.persistence import Trade
|
from freqtrade.persistence import Trade
|
||||||
|
|
||||||
|
|
||||||
def test_update(limit_buy_order, limit_sell_order):
|
def test_update_with_bittrex(limit_buy_order, limit_sell_order):
|
||||||
|
"""
|
||||||
|
On this test we will buy and sell a crypto currency.
|
||||||
|
|
||||||
|
Buy
|
||||||
|
- Buy: 90.99181073 Crypto at 0.00001099 BTC (90.99181073*0.00001099 = 0.0009999 BTC)
|
||||||
|
- Buying fee: 0.25%
|
||||||
|
- Total cost of buy trade: 0.001002500 BTC ((90.99181073*0.00001099) + ((90.99181073*0.00001099)*0.0025))
|
||||||
|
|
||||||
|
Sell
|
||||||
|
- Sell: 90.99181073 Crypto at 0.00001173 BTC (90.99181073*0.00001173 = 0,00106733394 BTC)
|
||||||
|
- Selling fee: 0.25%
|
||||||
|
- Total cost of sell trade: 0.001064666 BTC ((90.99181073*0.00001173) - ((90.99181073*0.00001173)*0.0025))
|
||||||
|
|
||||||
|
Profit/Loss: +0.000062166 BTC (Sell:0.001064666 - Buy:0.001002500)
|
||||||
|
Profit/Loss percentage: 0.0620 ((0.001064666/0.001002500)-1 = 6.20%)
|
||||||
|
|
||||||
|
:param limit_buy_order:
|
||||||
|
:param limit_sell_order:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
trade = Trade(
|
trade = Trade(
|
||||||
pair='BTC_ETH',
|
pair='BTC_ETH',
|
||||||
stake_amount=1.00,
|
stake_amount=0.001,
|
||||||
fee=0.1,
|
fee=0.0025,
|
||||||
exchange=Exchanges.BITTREX,
|
exchange=Exchanges.BITTREX,
|
||||||
)
|
)
|
||||||
assert trade.open_order_id is None
|
assert trade.open_order_id is None
|
||||||
@ -20,18 +41,40 @@ def test_update(limit_buy_order, limit_sell_order):
|
|||||||
trade.open_order_id = 'something'
|
trade.open_order_id = 'something'
|
||||||
trade.update(limit_buy_order)
|
trade.update(limit_buy_order)
|
||||||
assert trade.open_order_id is None
|
assert trade.open_order_id is None
|
||||||
assert trade.open_rate == 0.07256061
|
assert trade.open_rate == 0.00001099
|
||||||
assert trade.close_profit is None
|
assert trade.close_profit is None
|
||||||
assert trade.close_date is None
|
assert trade.close_date is None
|
||||||
|
|
||||||
trade.open_order_id = 'something'
|
trade.open_order_id = 'something'
|
||||||
trade.update(limit_sell_order)
|
trade.update(limit_sell_order)
|
||||||
assert trade.open_order_id is None
|
assert trade.open_order_id is None
|
||||||
assert trade.open_rate == 0.07256061
|
assert trade.close_rate == 0.00001173
|
||||||
assert trade.close_profit == 0.00546755
|
assert trade.close_profit == 0.06201057
|
||||||
assert trade.close_date is not None
|
assert trade.close_date is not None
|
||||||
|
|
||||||
|
|
||||||
|
def test_calc_open_close_trade_price(limit_buy_order, limit_sell_order):
|
||||||
|
trade = Trade(
|
||||||
|
pair='BTC_ETH',
|
||||||
|
stake_amount=0.001,
|
||||||
|
fee=0.0025,
|
||||||
|
exchange=Exchanges.BITTREX,
|
||||||
|
)
|
||||||
|
|
||||||
|
trade.open_order_id = 'something'
|
||||||
|
trade.update(limit_buy_order)
|
||||||
|
assert trade.calc_open_trade_price() == 0.001002500
|
||||||
|
|
||||||
|
trade.update(limit_sell_order)
|
||||||
|
assert trade.calc_close_trade_price() == 0.0010646656
|
||||||
|
|
||||||
|
# Profit in BTC
|
||||||
|
assert trade.calc_profit() == 0.00006217
|
||||||
|
|
||||||
|
# Profit in percent
|
||||||
|
assert trade.calc_profit_percent() == 0.06201057
|
||||||
|
|
||||||
|
|
||||||
def test_update_open_order(limit_buy_order):
|
def test_update_open_order(limit_buy_order):
|
||||||
trade = Trade(
|
trade = Trade(
|
||||||
pair='BTC_ETH',
|
pair='BTC_ETH',
|
||||||
@ -64,3 +107,103 @@ def test_update_invalid_order(limit_buy_order):
|
|||||||
limit_buy_order['type'] = 'invalid'
|
limit_buy_order['type'] = 'invalid'
|
||||||
with pytest.raises(ValueError, match=r'Unknown order type'):
|
with pytest.raises(ValueError, match=r'Unknown order type'):
|
||||||
trade.update(limit_buy_order)
|
trade.update(limit_buy_order)
|
||||||
|
|
||||||
|
|
||||||
|
def test_calc_open_trade_price(limit_buy_order):
|
||||||
|
trade = Trade(
|
||||||
|
pair='BTC_ETH',
|
||||||
|
stake_amount=0.001,
|
||||||
|
fee=0.0025,
|
||||||
|
exchange=Exchanges.BITTREX,
|
||||||
|
)
|
||||||
|
trade.open_order_id = 'open_trade'
|
||||||
|
trade.update(limit_buy_order) # Buy @ 0.00001099
|
||||||
|
|
||||||
|
# Get the open rate price with the standard fee rate
|
||||||
|
assert trade.calc_open_trade_price() == 0.001002500
|
||||||
|
|
||||||
|
# Get the open rate price with a custom fee rate
|
||||||
|
assert trade.calc_open_trade_price(fee=0.003) == 0.001003000
|
||||||
|
|
||||||
|
|
||||||
|
def test_calc_close_trade_price(limit_buy_order, limit_sell_order):
|
||||||
|
trade = Trade(
|
||||||
|
pair='BTC_ETH',
|
||||||
|
stake_amount=0.001,
|
||||||
|
fee=0.0025,
|
||||||
|
exchange=Exchanges.BITTREX,
|
||||||
|
)
|
||||||
|
trade.open_order_id = 'close_trade'
|
||||||
|
trade.update(limit_buy_order) # Buy @ 0.00001099
|
||||||
|
|
||||||
|
# Get the close rate price with a custom close rate and a regular fee rate
|
||||||
|
assert trade.calc_close_trade_price(rate=0.00001234) == 0.0011200318
|
||||||
|
|
||||||
|
# Get the close rate price with a custom close rate and a custom fee rate
|
||||||
|
assert trade.calc_close_trade_price(rate=0.00001234, fee=0.003) == 0.0011194704
|
||||||
|
|
||||||
|
# Test when we apply a Sell order, and ask price with a custom fee rate
|
||||||
|
trade.update(limit_sell_order)
|
||||||
|
assert trade.calc_close_trade_price(fee=0.005) == 0.0010619972
|
||||||
|
|
||||||
|
|
||||||
|
def test_calc_profit(limit_buy_order, limit_sell_order):
|
||||||
|
trade = Trade(
|
||||||
|
pair='BTC_ETH',
|
||||||
|
stake_amount=0.001,
|
||||||
|
fee=0.0025,
|
||||||
|
exchange=Exchanges.BITTREX,
|
||||||
|
)
|
||||||
|
trade.open_order_id = 'profit_percent'
|
||||||
|
trade.update(limit_buy_order) # Buy @ 0.00001099
|
||||||
|
|
||||||
|
# Custom closing rate and regular fee rate
|
||||||
|
# Higher than open rate
|
||||||
|
assert trade.calc_profit(rate=0.00001234) == 0.00011753
|
||||||
|
# Lower than open rate
|
||||||
|
assert trade.calc_profit(rate=0.00000123) == -0.00089086
|
||||||
|
|
||||||
|
# Custom closing rate and custom fee rate
|
||||||
|
# Higher than open rate
|
||||||
|
assert trade.calc_profit(rate=0.00001234, fee=0.003) == 0.00011697
|
||||||
|
# Lower than open rate
|
||||||
|
assert trade.calc_profit(rate=0.00000123, fee=0.003) == -0.00089092
|
||||||
|
|
||||||
|
# Only custom fee without sell order applied
|
||||||
|
with pytest.raises(TypeError):
|
||||||
|
trade.calc_profit(fee=0.003)
|
||||||
|
|
||||||
|
# Test when we apply a Sell order. Sell higher than open rate @ 0.00001173
|
||||||
|
trade.update(limit_sell_order)
|
||||||
|
assert trade.calc_profit() == 0.00006217
|
||||||
|
|
||||||
|
# Test with a custom fee rate on the close trade
|
||||||
|
assert trade.calc_profit(fee=0.003) == 0.00006163
|
||||||
|
|
||||||
|
|
||||||
|
def test_calc_profit_percent(limit_buy_order, limit_sell_order):
|
||||||
|
trade = Trade(
|
||||||
|
pair='BTC_ETH',
|
||||||
|
stake_amount=0.001,
|
||||||
|
fee=0.0025,
|
||||||
|
exchange=Exchanges.BITTREX,
|
||||||
|
)
|
||||||
|
trade.open_order_id = 'profit_percent'
|
||||||
|
trade.update(limit_buy_order) # Buy @ 0.00001099
|
||||||
|
|
||||||
|
# Get percent of profit with a custom rate (Higher than open rate)
|
||||||
|
assert trade.calc_profit_percent(rate=0.00001234) == 0.1172387
|
||||||
|
|
||||||
|
# Get percent of profit with a custom rate (Lower than open rate)
|
||||||
|
assert trade.calc_profit_percent(rate=0.00000123) == -0.88863827
|
||||||
|
|
||||||
|
# Only custom fee without sell order applied
|
||||||
|
with pytest.raises(TypeError):
|
||||||
|
trade.calc_profit_percent(fee=0.003)
|
||||||
|
|
||||||
|
# Test when we apply a Sell order. Sell higher than open rate @ 0.00001173
|
||||||
|
trade.update(limit_sell_order)
|
||||||
|
assert trade.calc_profit_percent() == 0.06201057
|
||||||
|
|
||||||
|
# Test with a custom fee rate on the close trade
|
||||||
|
assert trade.calc_profit_percent(fee=0.003) == 0.0614782
|
||||||
|
@ -102,7 +102,7 @@ def test_status_handle(default_conf, update, ticker, mocker):
|
|||||||
msg_mock.reset_mock()
|
msg_mock.reset_mock()
|
||||||
|
|
||||||
# Create some test data
|
# Create some test data
|
||||||
create_trade(15.0)
|
create_trade(0.001)
|
||||||
# Trigger status while we have a fulfilled order for the open trade
|
# Trigger status while we have a fulfilled order for the open trade
|
||||||
_status(bot=MagicMock(), update=update)
|
_status(bot=MagicMock(), update=update)
|
||||||
|
|
||||||
@ -151,7 +151,7 @@ def test_status_table_handle(default_conf, update, ticker, mocker):
|
|||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
|
|
||||||
|
|
||||||
def test_profit_handle(default_conf, update, ticker, limit_buy_order, limit_sell_order, mocker):
|
def test_profit_handle(default_conf, update, ticker, ticker_sell_up, limit_buy_order, limit_sell_order, mocker):
|
||||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||||
msg_mock = MagicMock()
|
msg_mock = MagicMock()
|
||||||
@ -171,7 +171,7 @@ def test_profit_handle(default_conf, update, ticker, limit_buy_order, limit_sell
|
|||||||
msg_mock.reset_mock()
|
msg_mock.reset_mock()
|
||||||
|
|
||||||
# Create some test data
|
# Create some test data
|
||||||
create_trade(15.0)
|
create_trade(0.001)
|
||||||
trade = Trade.query.first()
|
trade = Trade.query.first()
|
||||||
|
|
||||||
# Simulate fulfilled LIMIT_BUY order for trade
|
# Simulate fulfilled LIMIT_BUY order for trade
|
||||||
@ -182,7 +182,10 @@ def test_profit_handle(default_conf, update, ticker, limit_buy_order, limit_sell
|
|||||||
assert 'no closed trade' in msg_mock.call_args_list[-1][0][0]
|
assert 'no closed trade' in msg_mock.call_args_list[-1][0][0]
|
||||||
msg_mock.reset_mock()
|
msg_mock.reset_mock()
|
||||||
|
|
||||||
# Simulate fulfilled LIMIT_SELL order for trade
|
# Update the ticker with a market going up
|
||||||
|
mocker.patch.multiple('freqtrade.main.exchange',
|
||||||
|
validate_pairs=MagicMock(),
|
||||||
|
get_ticker=ticker_sell_up)
|
||||||
trade.update(limit_sell_order)
|
trade.update(limit_sell_order)
|
||||||
|
|
||||||
trade.close_date = datetime.utcnow()
|
trade.close_date = datetime.utcnow()
|
||||||
@ -190,11 +193,12 @@ def test_profit_handle(default_conf, update, ticker, limit_buy_order, limit_sell
|
|||||||
|
|
||||||
_profit(bot=MagicMock(), update=update)
|
_profit(bot=MagicMock(), update=update)
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert '*ROI All trades:* `0.00765279 BTC (10.05%)`' in msg_mock.call_args_list[-1][0][0]
|
assert '*ROI Trade closed:* `0.00006217 BTC (6.20%)`' in msg_mock.call_args_list[-1][0][0]
|
||||||
assert 'Best Performing:* `BTC_ETH: 10.05%`' 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]
|
||||||
|
|
||||||
|
|
||||||
def test_forcesell_handle(default_conf, update, ticker, mocker):
|
def test_forcesell_handle(default_conf, update, ticker, ticker_sell_up, mocker):
|
||||||
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||||
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||||
rpc_mock = mocker.patch('freqtrade.main.rpc.send_msg', MagicMock())
|
rpc_mock = mocker.patch('freqtrade.main.rpc.send_msg', MagicMock())
|
||||||
@ -208,7 +212,44 @@ def test_forcesell_handle(default_conf, update, ticker, mocker):
|
|||||||
init(default_conf, create_engine('sqlite://'))
|
init(default_conf, create_engine('sqlite://'))
|
||||||
|
|
||||||
# Create some test data
|
# Create some test data
|
||||||
create_trade(15.0)
|
create_trade(0.001)
|
||||||
|
|
||||||
|
trade = Trade.query.first()
|
||||||
|
assert trade
|
||||||
|
|
||||||
|
# Increase the price and sell it
|
||||||
|
mocker.patch.multiple('freqtrade.main.exchange',
|
||||||
|
validate_pairs=MagicMock(),
|
||||||
|
get_ticker=ticker_sell_up)
|
||||||
|
|
||||||
|
update.message.text = '/forcesell 1'
|
||||||
|
_forcesell(bot=MagicMock(), update=update)
|
||||||
|
|
||||||
|
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]
|
||||||
|
|
||||||
|
|
||||||
|
def test_forcesell_down_handle(default_conf, update, ticker, ticker_sell_down, mocker):
|
||||||
|
mocker.patch.dict('freqtrade.main._CONF', default_conf)
|
||||||
|
mocker.patch('freqtrade.main.get_signal', side_effect=lambda s, t: True)
|
||||||
|
rpc_mock = mocker.patch('freqtrade.main.rpc.send_msg', MagicMock())
|
||||||
|
mocker.patch.multiple('freqtrade.rpc.telegram',
|
||||||
|
_CONF=default_conf,
|
||||||
|
init=MagicMock(),
|
||||||
|
send_msg=MagicMock())
|
||||||
|
mocker.patch.multiple('freqtrade.main.exchange',
|
||||||
|
validate_pairs=MagicMock(),
|
||||||
|
get_ticker=ticker)
|
||||||
|
init(default_conf, create_engine('sqlite://'))
|
||||||
|
|
||||||
|
# Create some test data
|
||||||
|
create_trade(0.001)
|
||||||
|
|
||||||
|
## Decrease the price and sell it
|
||||||
|
mocker.patch.multiple('freqtrade.main.exchange',
|
||||||
|
validate_pairs=MagicMock(),
|
||||||
|
get_ticker=ticker_sell_down)
|
||||||
|
|
||||||
trade = Trade.query.first()
|
trade = Trade.query.first()
|
||||||
assert trade
|
assert trade
|
||||||
@ -218,7 +259,7 @@ def test_forcesell_handle(default_conf, update, ticker, mocker):
|
|||||||
|
|
||||||
assert rpc_mock.call_count == 2
|
assert rpc_mock.call_count == 2
|
||||||
assert 'Selling [BTC/ETH]' in rpc_mock.call_args_list[-1][0][0]
|
assert 'Selling [BTC/ETH]' in rpc_mock.call_args_list[-1][0][0]
|
||||||
assert '0.07256061 (profit: ~-0.64%)' 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]
|
||||||
|
|
||||||
|
|
||||||
def test_exec_forcesell_open_orders(default_conf, ticker, mocker):
|
def test_exec_forcesell_open_orders(default_conf, ticker, mocker):
|
||||||
@ -260,7 +301,7 @@ def test_forcesell_all_handle(default_conf, update, ticker, mocker):
|
|||||||
|
|
||||||
# Create some test data
|
# Create some test data
|
||||||
for _ in range(4):
|
for _ in range(4):
|
||||||
create_trade(15.0)
|
create_trade(0.001)
|
||||||
rpc_mock.reset_mock()
|
rpc_mock.reset_mock()
|
||||||
|
|
||||||
update.message.text = '/forcesell all'
|
update.message.text = '/forcesell all'
|
||||||
@ -268,7 +309,7 @@ def test_forcesell_all_handle(default_conf, update, ticker, mocker):
|
|||||||
|
|
||||||
assert rpc_mock.call_count == 4
|
assert rpc_mock.call_count == 4
|
||||||
for args in rpc_mock.call_args_list:
|
for args in rpc_mock.call_args_list:
|
||||||
assert '0.07256061 (profit: ~-0.64%)' in args[0][0]
|
assert '0.00001098 (profit: ~-0.59%, -0.00000591)' in args[0][0]
|
||||||
|
|
||||||
|
|
||||||
def test_forcesell_handle_invalid(default_conf, update, mocker):
|
def test_forcesell_handle_invalid(default_conf, update, mocker):
|
||||||
@ -323,7 +364,7 @@ def test_performance_handle(
|
|||||||
init(default_conf, create_engine('sqlite://'))
|
init(default_conf, create_engine('sqlite://'))
|
||||||
|
|
||||||
# Create some test data
|
# Create some test data
|
||||||
create_trade(15.0)
|
create_trade(0.001)
|
||||||
trade = Trade.query.first()
|
trade = Trade.query.first()
|
||||||
assert trade
|
assert trade
|
||||||
|
|
||||||
@ -339,7 +380,8 @@ def test_performance_handle(
|
|||||||
_performance(bot=MagicMock(), update=update)
|
_performance(bot=MagicMock(), update=update)
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert 'Performance' in msg_mock.call_args_list[0][0][0]
|
assert 'Performance' in msg_mock.call_args_list[0][0][0]
|
||||||
assert '<code>BTC_ETH\t10.05%</code>' in msg_mock.call_args_list[0][0][0]
|
assert '<code>BTC_ETH\t6.20%</code>' in msg_mock.call_args_list[0][0][0]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_daily_handle(
|
def test_daily_handle(
|
||||||
@ -358,7 +400,7 @@ def test_daily_handle(
|
|||||||
init(default_conf, create_engine('sqlite://'))
|
init(default_conf, create_engine('sqlite://'))
|
||||||
|
|
||||||
# Create some test data
|
# Create some test data
|
||||||
create_trade(15.0)
|
create_trade(0.001)
|
||||||
trade = Trade.query.first()
|
trade = Trade.query.first()
|
||||||
assert trade
|
assert trade
|
||||||
|
|
||||||
@ -371,14 +413,14 @@ def test_daily_handle(
|
|||||||
trade.close_date = datetime.utcnow()
|
trade.close_date = datetime.utcnow()
|
||||||
trade.is_open = False
|
trade.is_open = False
|
||||||
|
|
||||||
# try valid data
|
# Try valid data
|
||||||
update.message.text = '/daily 7'
|
update.message.text = '/daily 2'
|
||||||
_daily(bot=MagicMock(), update=update)
|
_daily(bot=MagicMock(), update=update)
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert 'Daily' in msg_mock.call_args_list[0][0][0]
|
assert 'Daily' in msg_mock.call_args_list[0][0][0]
|
||||||
assert str(date.today()) + ' 1.50701325 BTC' 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]
|
||||||
|
|
||||||
# try invalid data
|
# Try invalid data
|
||||||
msg_mock.reset_mock()
|
msg_mock.reset_mock()
|
||||||
update_state(State.RUNNING)
|
update_state(State.RUNNING)
|
||||||
update.message.text = '/daily -2'
|
update.message.text = '/daily -2'
|
||||||
@ -409,7 +451,7 @@ def test_count_handle(default_conf, update, ticker, mocker):
|
|||||||
update_state(State.RUNNING)
|
update_state(State.RUNNING)
|
||||||
|
|
||||||
# Create some test data
|
# Create some test data
|
||||||
create_trade(15.0)
|
create_trade(0.001)
|
||||||
msg_mock.reset_mock()
|
msg_mock.reset_mock()
|
||||||
_count(bot=MagicMock(), update=update)
|
_count(bot=MagicMock(), update=update)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user