Merge branch 'freqtrade:develop' into develop
This commit is contained in:
@@ -17,8 +17,8 @@ repos:
|
|||||||
- types-filelock==3.2.7
|
- types-filelock==3.2.7
|
||||||
- types-requests==2.30.0.0
|
- types-requests==2.30.0.0
|
||||||
- types-tabulate==0.9.0.2
|
- types-tabulate==0.9.0.2
|
||||||
- types-python-dateutil==2.8.19.12
|
- types-python-dateutil==2.8.19.13
|
||||||
- SQLAlchemy==2.0.12
|
- SQLAlchemy==2.0.13
|
||||||
# stages: [push]
|
# stages: [push]
|
||||||
|
|
||||||
- repo: https://github.com/pycqa/isort
|
- repo: https://github.com/pycqa/isort
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
markdown==3.3.7
|
markdown==3.3.7
|
||||||
mkdocs==1.4.3
|
mkdocs==1.4.3
|
||||||
mkdocs-material==9.1.10
|
mkdocs-material==9.1.12
|
||||||
mdx_truly_sane_lists==1.3
|
mdx_truly_sane_lists==1.3
|
||||||
pymdown-extensions==9.11
|
pymdown-extensions==10.0.1
|
||||||
jinja2==3.1.2
|
jinja2==3.1.2
|
||||||
|
|||||||
@@ -1018,7 +1018,7 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
'base_currency': self.exchange.get_pair_base_currency(trade.pair),
|
'base_currency': self.exchange.get_pair_base_currency(trade.pair),
|
||||||
'fiat_currency': self.config.get('fiat_display_currency', None),
|
'fiat_currency': self.config.get('fiat_display_currency', None),
|
||||||
'amount': order.safe_amount_after_fee if fill else (order.amount or trade.amount),
|
'amount': order.safe_amount_after_fee if fill else (order.amount or trade.amount),
|
||||||
'open_date': trade.open_date or datetime.utcnow(),
|
'open_date': trade.open_date_utc or datetime.now(timezone.utc),
|
||||||
'current_rate': current_rate,
|
'current_rate': current_rate,
|
||||||
'sub_trade': sub_trade,
|
'sub_trade': sub_trade,
|
||||||
}
|
}
|
||||||
@@ -1741,8 +1741,8 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
'enter_tag': trade.enter_tag,
|
'enter_tag': trade.enter_tag,
|
||||||
'sell_reason': trade.exit_reason, # Deprecated
|
'sell_reason': trade.exit_reason, # Deprecated
|
||||||
'exit_reason': trade.exit_reason,
|
'exit_reason': trade.exit_reason,
|
||||||
'open_date': trade.open_date,
|
'open_date': trade.open_date_utc,
|
||||||
'close_date': trade.close_date or datetime.utcnow(),
|
'close_date': trade.close_date_utc or datetime.now(timezone.utc),
|
||||||
'stake_amount': trade.stake_amount,
|
'stake_amount': trade.stake_amount,
|
||||||
'stake_currency': self.config['stake_currency'],
|
'stake_currency': self.config['stake_currency'],
|
||||||
'base_currency': self.exchange.get_pair_base_currency(trade.pair),
|
'base_currency': self.exchange.get_pair_base_currency(trade.pair),
|
||||||
|
|||||||
@@ -425,7 +425,7 @@ class LocalTrade():
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def close_date_utc(self):
|
def close_date_utc(self):
|
||||||
return self.close_date.replace(tzinfo=timezone.utc)
|
return self.close_date.replace(tzinfo=timezone.utc) if self.close_date else None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def entry_side(self) -> str:
|
def entry_side(self) -> str:
|
||||||
|
|||||||
@@ -100,8 +100,10 @@ class Profit(BaseModel):
|
|||||||
trade_count: int
|
trade_count: int
|
||||||
closed_trade_count: int
|
closed_trade_count: int
|
||||||
first_trade_date: str
|
first_trade_date: str
|
||||||
|
first_trade_humanized: str
|
||||||
first_trade_timestamp: int
|
first_trade_timestamp: int
|
||||||
latest_trade_date: str
|
latest_trade_date: str
|
||||||
|
latest_trade_humanized: str
|
||||||
latest_trade_timestamp: int
|
latest_trade_timestamp: int
|
||||||
avg_duration: str
|
avg_duration: str
|
||||||
best_pair: str
|
best_pair: str
|
||||||
|
|||||||
@@ -45,7 +45,8 @@ logger = logging.getLogger(__name__)
|
|||||||
# 2.25: Add several profit values to /status endpoint
|
# 2.25: Add several profit values to /status endpoint
|
||||||
# 2.26: increase /balance output
|
# 2.26: increase /balance output
|
||||||
# 2.27: Add /trades/<id>/reload endpoint
|
# 2.27: Add /trades/<id>/reload endpoint
|
||||||
API_VERSION = 2.27
|
# 2.28: Switch reload endpoint to Post
|
||||||
|
API_VERSION = 2.28
|
||||||
|
|
||||||
# Public API, requires no auth.
|
# Public API, requires no auth.
|
||||||
router_public = APIRouter()
|
router_public = APIRouter()
|
||||||
@@ -133,7 +134,7 @@ def trade_cancel_open_order(tradeid: int, rpc: RPC = Depends(get_rpc)):
|
|||||||
return rpc._rpc_trade_status([tradeid])[0]
|
return rpc._rpc_trade_status([tradeid])[0]
|
||||||
|
|
||||||
|
|
||||||
@router.get('/trades/{tradeid}/reload', response_model=OpenTradeSchema, tags=['trading'])
|
@router.post('/trades/{tradeid}/reload', response_model=OpenTradeSchema, tags=['trading'])
|
||||||
def trade_reload(tradeid: int, rpc: RPC = Depends(get_rpc)):
|
def trade_reload(tradeid: int, rpc: RPC = Depends(get_rpc)):
|
||||||
rpc._rpc_reload_trade_from_exchange(tradeid)
|
rpc._rpc_reload_trade_from_exchange(tradeid)
|
||||||
return rpc._rpc_trade_status([tradeid])[0]
|
return rpc._rpc_trade_status([tradeid])[0]
|
||||||
|
|||||||
@@ -540,8 +540,8 @@ class RPC:
|
|||||||
fiat_display_currency
|
fiat_display_currency
|
||||||
) if self._fiat_converter else 0
|
) if self._fiat_converter else 0
|
||||||
|
|
||||||
first_date = trades[0].open_date if trades else None
|
first_date = trades[0].open_date_utc if trades else None
|
||||||
last_date = trades[-1].open_date if trades else None
|
last_date = trades[-1].open_date_utc if trades else None
|
||||||
num = float(len(durations) or 1)
|
num = float(len(durations) or 1)
|
||||||
bot_start = KeyValueStore.get_datetime_value(KeyStoreKeys.BOT_START_TIME)
|
bot_start = KeyValueStore.get_datetime_value(KeyStoreKeys.BOT_START_TIME)
|
||||||
return {
|
return {
|
||||||
@@ -563,9 +563,11 @@ class RPC:
|
|||||||
'profit_all_fiat': profit_all_fiat,
|
'profit_all_fiat': profit_all_fiat,
|
||||||
'trade_count': len(trades),
|
'trade_count': len(trades),
|
||||||
'closed_trade_count': len([t for t in trades if not t.is_open]),
|
'closed_trade_count': len([t for t in trades if not t.is_open]),
|
||||||
'first_trade_date': arrow.get(first_date).humanize() if first_date else '',
|
'first_trade_date': first_date.strftime(DATETIME_PRINT_FORMAT) if first_date else '',
|
||||||
|
'first_trade_humanized': arrow.get(first_date).humanize() if first_date else '',
|
||||||
'first_trade_timestamp': int(first_date.timestamp() * 1000) if first_date else 0,
|
'first_trade_timestamp': int(first_date.timestamp() * 1000) if first_date else 0,
|
||||||
'latest_trade_date': arrow.get(last_date).humanize() if last_date else '',
|
'latest_trade_date': last_date.strftime(DATETIME_PRINT_FORMAT) if last_date else '',
|
||||||
|
'latest_trade_humanized': arrow.get(last_date).humanize() if last_date else '',
|
||||||
'latest_trade_timestamp': int(last_date.timestamp() * 1000) if last_date else 0,
|
'latest_trade_timestamp': int(last_date.timestamp() * 1000) if last_date else 0,
|
||||||
'avg_duration': str(timedelta(seconds=sum(durations) / num)).split('.')[0],
|
'avg_duration': str(timedelta(seconds=sum(durations) / num)).split('.')[0],
|
||||||
'best_pair': best_pair[0] if best_pair else '',
|
'best_pair': best_pair[0] if best_pair else '',
|
||||||
|
|||||||
@@ -853,8 +853,8 @@ class Telegram(RPCHandler):
|
|||||||
profit_all_percent = stats['profit_all_percent']
|
profit_all_percent = stats['profit_all_percent']
|
||||||
profit_all_fiat = stats['profit_all_fiat']
|
profit_all_fiat = stats['profit_all_fiat']
|
||||||
trade_count = stats['trade_count']
|
trade_count = stats['trade_count']
|
||||||
first_trade_date = stats['first_trade_date']
|
first_trade_date = f"{stats['first_trade_humanized']} ({stats['first_trade_date']})"
|
||||||
latest_trade_date = stats['latest_trade_date']
|
latest_trade_date = f"{stats['latest_trade_humanized']} ({stats['latest_trade_date']})"
|
||||||
avg_duration = stats['avg_duration']
|
avg_duration = stats['avg_duration']
|
||||||
best_pair = stats['best_pair']
|
best_pair = stats['best_pair']
|
||||||
best_pair_profit_ratio = stats['best_pair_profit_ratio']
|
best_pair_profit_ratio = stats['best_pair_profit_ratio']
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
-r docs/requirements-docs.txt
|
-r docs/requirements-docs.txt
|
||||||
|
|
||||||
coveralls==3.3.1
|
coveralls==3.3.1
|
||||||
ruff==0.0.265
|
ruff==0.0.267
|
||||||
mypy==1.2.0
|
mypy==1.3.0
|
||||||
pre-commit==3.3.1
|
pre-commit==3.3.1
|
||||||
pytest==7.3.1
|
pytest==7.3.1
|
||||||
pytest-asyncio==0.21.0
|
pytest-asyncio==0.21.0
|
||||||
@@ -27,4 +27,4 @@ types-cachetools==5.3.0.5
|
|||||||
types-filelock==3.2.7
|
types-filelock==3.2.7
|
||||||
types-requests==2.30.0.0
|
types-requests==2.30.0.0
|
||||||
types-tabulate==0.9.0.2
|
types-tabulate==0.9.0.2
|
||||||
types-python-dateutil==2.8.19.12
|
types-python-dateutil==2.8.19.13
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
-r requirements-freqai.txt
|
-r requirements-freqai.txt
|
||||||
|
|
||||||
# Required for freqai-rl
|
# Required for freqai-rl
|
||||||
torch==2.0.0
|
torch==2.0.1
|
||||||
#until these branches will be released we can use this
|
#until these branches will be released we can use this
|
||||||
gymnasium==0.28.1
|
gymnasium==0.28.1
|
||||||
stable_baselines3==2.0.0a5
|
stable_baselines3==2.0.0a5
|
||||||
|
|||||||
+5
-4
@@ -2,10 +2,11 @@ numpy==1.24.3
|
|||||||
pandas==2.0.1
|
pandas==2.0.1
|
||||||
pandas-ta==0.3.14b
|
pandas-ta==0.3.14b
|
||||||
|
|
||||||
ccxt==3.0.97
|
ccxt==3.0.103
|
||||||
cryptography==40.0.2
|
cryptography==40.0.2; platform_machine != 'armv7l'
|
||||||
|
cryptography==40.0.1; platform_machine == 'armv7l'
|
||||||
aiohttp==3.8.4
|
aiohttp==3.8.4
|
||||||
SQLAlchemy==2.0.12
|
SQLAlchemy==2.0.13
|
||||||
python-telegram-bot==20.3
|
python-telegram-bot==20.3
|
||||||
# can't be hard-pinned due to telegram-bot pinning httpx with ~
|
# can't be hard-pinned due to telegram-bot pinning httpx with ~
|
||||||
httpx>=0.23.3
|
httpx>=0.23.3
|
||||||
@@ -40,7 +41,7 @@ sdnotify==0.3.2
|
|||||||
fastapi==0.95.1
|
fastapi==0.95.1
|
||||||
pydantic==1.10.7
|
pydantic==1.10.7
|
||||||
uvicorn==0.22.0
|
uvicorn==0.22.0
|
||||||
pyjwt==2.6.0
|
pyjwt==2.7.0
|
||||||
aiofiles==23.1.0
|
aiofiles==23.1.0
|
||||||
psutil==5.9.5
|
psutil==5.9.5
|
||||||
|
|
||||||
|
|||||||
@@ -239,7 +239,7 @@ def test_interest(fee, exchange, is_short, lev, minutes, rate, interest,
|
|||||||
stake_amount=20.0,
|
stake_amount=20.0,
|
||||||
amount=30.0,
|
amount=30.0,
|
||||||
open_rate=2.0,
|
open_rate=2.0,
|
||||||
open_date=datetime.utcnow() - timedelta(minutes=minutes),
|
open_date=datetime.now(timezone.utc) - timedelta(minutes=minutes),
|
||||||
fee_open=fee.return_value,
|
fee_open=fee.return_value,
|
||||||
fee_close=fee.return_value,
|
fee_close=fee.return_value,
|
||||||
exchange=exchange,
|
exchange=exchange,
|
||||||
@@ -2063,7 +2063,7 @@ def test_trade_truncates_string_fields():
|
|||||||
stake_amount=20.0,
|
stake_amount=20.0,
|
||||||
amount=30.0,
|
amount=30.0,
|
||||||
open_rate=2.0,
|
open_rate=2.0,
|
||||||
open_date=datetime.utcnow() - timedelta(minutes=20),
|
open_date=datetime.now(timezone.utc) - timedelta(minutes=20),
|
||||||
fee_open=0.001,
|
fee_open=0.001,
|
||||||
fee_close=0.001,
|
fee_close=0.001,
|
||||||
exchange='binance',
|
exchange='binance',
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import random
|
import random
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta, timezone
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
@@ -24,8 +24,8 @@ def generate_mock_trade(pair: str, fee: float, is_open: bool,
|
|||||||
stake_amount=0.01,
|
stake_amount=0.01,
|
||||||
fee_open=fee,
|
fee_open=fee,
|
||||||
fee_close=fee,
|
fee_close=fee,
|
||||||
open_date=datetime.utcnow() - timedelta(minutes=min_ago_open or 200),
|
open_date=datetime.now(timezone.utc) - timedelta(minutes=min_ago_open or 200),
|
||||||
close_date=datetime.utcnow() - timedelta(minutes=min_ago_close or 30),
|
close_date=datetime.now(timezone.utc) - timedelta(minutes=min_ago_close or 30),
|
||||||
open_rate=open_rate,
|
open_rate=open_rate,
|
||||||
is_open=is_open,
|
is_open=is_open,
|
||||||
amount=0.01 / open_rate,
|
amount=0.01 / open_rate,
|
||||||
@@ -87,9 +87,9 @@ def test_protectionmanager(mocker, default_conf):
|
|||||||
for handler in freqtrade.protections._protection_handlers:
|
for handler in freqtrade.protections._protection_handlers:
|
||||||
assert handler.name in constants.AVAILABLE_PROTECTIONS
|
assert handler.name in constants.AVAILABLE_PROTECTIONS
|
||||||
if not handler.has_global_stop:
|
if not handler.has_global_stop:
|
||||||
assert handler.global_stop(datetime.utcnow(), '*') is None
|
assert handler.global_stop(datetime.now(timezone.utc), '*') is None
|
||||||
if not handler.has_local_stop:
|
if not handler.has_local_stop:
|
||||||
assert handler.stop_per_pair('XRP/BTC', datetime.utcnow(), '*') is None
|
assert handler.stop_per_pair('XRP/BTC', datetime.now(timezone.utc), '*') is None
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('timeframe,expected,protconf', [
|
@pytest.mark.parametrize('timeframe,expected,protconf', [
|
||||||
|
|||||||
@@ -261,8 +261,7 @@ def test_rpc_status_table(default_conf, ticker, fee, mocker) -> None:
|
|||||||
assert isnan(fiat_profit_sum)
|
assert isnan(fiat_profit_sum)
|
||||||
|
|
||||||
|
|
||||||
def test__rpc_timeunit_profit(default_conf_usdt, ticker, fee,
|
def test__rpc_timeunit_profit(default_conf_usdt, ticker, fee, markets, mocker) -> None:
|
||||||
limit_buy_order, limit_sell_order, markets, mocker) -> None:
|
|
||||||
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
|
||||||
mocker.patch.multiple(
|
mocker.patch.multiple(
|
||||||
EXMS,
|
EXMS,
|
||||||
@@ -295,7 +294,7 @@ def test__rpc_timeunit_profit(default_conf_usdt, ticker, fee,
|
|||||||
assert day['starting_balance'] in (pytest.approx(1062.37), pytest.approx(1066.46))
|
assert day['starting_balance'] in (pytest.approx(1062.37), pytest.approx(1066.46))
|
||||||
assert day['fiat_value'] in (0.0, )
|
assert day['fiat_value'] in (0.0, )
|
||||||
# ensure first day is current date
|
# ensure first day is current date
|
||||||
assert str(days['data'][0]['date']) == str(datetime.utcnow().date())
|
assert str(days['data'][0]['date']) == str(datetime.now(timezone.utc).date())
|
||||||
|
|
||||||
# Try invalid data
|
# Try invalid data
|
||||||
with pytest.raises(RPCException, match=r'.*must be an integer greater than 0*'):
|
with pytest.raises(RPCException, match=r'.*must be an integer greater than 0*'):
|
||||||
@@ -415,8 +414,8 @@ def test_rpc_trade_statistics(default_conf_usdt, ticker, fee, mocker) -> None:
|
|||||||
assert pytest.approx(stats['profit_all_percent_mean']) == -57.86
|
assert pytest.approx(stats['profit_all_percent_mean']) == -57.86
|
||||||
assert pytest.approx(stats['profit_all_fiat']) == -85.205614098
|
assert pytest.approx(stats['profit_all_fiat']) == -85.205614098
|
||||||
assert stats['trade_count'] == 7
|
assert stats['trade_count'] == 7
|
||||||
assert stats['first_trade_date'] == '2 days ago'
|
assert stats['first_trade_humanized'] == '2 days ago'
|
||||||
assert stats['latest_trade_date'] == '17 minutes ago'
|
assert stats['latest_trade_humanized'] == '17 minutes ago'
|
||||||
assert stats['avg_duration'] in ('0:17:40')
|
assert stats['avg_duration'] in ('0:17:40')
|
||||||
assert stats['best_pair'] == 'XRP/USDT'
|
assert stats['best_pair'] == 'XRP/USDT'
|
||||||
assert stats['best_rate'] == 10.0
|
assert stats['best_rate'] == 10.0
|
||||||
@@ -426,8 +425,8 @@ def test_rpc_trade_statistics(default_conf_usdt, ticker, fee, mocker) -> None:
|
|||||||
MagicMock(side_effect=ExchangeError("Pair 'XRP/USDT' not available")))
|
MagicMock(side_effect=ExchangeError("Pair 'XRP/USDT' not available")))
|
||||||
stats = rpc._rpc_trade_statistics(stake_currency, fiat_display_currency)
|
stats = rpc._rpc_trade_statistics(stake_currency, fiat_display_currency)
|
||||||
assert stats['trade_count'] == 7
|
assert stats['trade_count'] == 7
|
||||||
assert stats['first_trade_date'] == '2 days ago'
|
assert stats['first_trade_humanized'] == '2 days ago'
|
||||||
assert stats['latest_trade_date'] == '17 minutes ago'
|
assert stats['latest_trade_humanized'] == '17 minutes ago'
|
||||||
assert stats['avg_duration'] in ('0:17:40')
|
assert stats['avg_duration'] in ('0:17:40')
|
||||||
assert stats['best_pair'] == 'XRP/USDT'
|
assert stats['best_pair'] == 'XRP/USDT'
|
||||||
assert stats['best_rate'] == 10.0
|
assert stats['best_rate'] == 10.0
|
||||||
|
|||||||
@@ -601,7 +601,7 @@ def test_api_daily(botclient, mocker, ticker, fee, markets):
|
|||||||
assert len(rc.json()['data']) == 7
|
assert len(rc.json()['data']) == 7
|
||||||
assert rc.json()['stake_currency'] == 'BTC'
|
assert rc.json()['stake_currency'] == 'BTC'
|
||||||
assert rc.json()['fiat_display_currency'] == 'USD'
|
assert rc.json()['fiat_display_currency'] == 'USD'
|
||||||
assert rc.json()['data'][0]['date'] == str(datetime.utcnow().date())
|
assert rc.json()['data'][0]['date'] == str(datetime.now(timezone.utc).date())
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('is_short', [True, False])
|
@pytest.mark.parametrize('is_short', [True, False])
|
||||||
@@ -755,7 +755,7 @@ def test_api_trade_reload_trade(botclient, mocker, fee, markets, ticker, is_shor
|
|||||||
cancel_stoploss_order=stoploss_mock,
|
cancel_stoploss_order=stoploss_mock,
|
||||||
)
|
)
|
||||||
|
|
||||||
rc = client_get(client, f"{BASE_URI}/trades/10/reload")
|
rc = client_post(client, f"{BASE_URI}/trades/10/reload")
|
||||||
assert_response(rc, 502)
|
assert_response(rc, 502)
|
||||||
assert 'Could not find trade with id 10.' in rc.json()['error']
|
assert 'Could not find trade with id 10.' in rc.json()['error']
|
||||||
assert ftbot.handle_onexchange_order.call_count == 0
|
assert ftbot.handle_onexchange_order.call_count == 0
|
||||||
@@ -763,7 +763,7 @@ def test_api_trade_reload_trade(botclient, mocker, fee, markets, ticker, is_shor
|
|||||||
create_mock_trades(fee, is_short=is_short)
|
create_mock_trades(fee, is_short=is_short)
|
||||||
Trade.commit()
|
Trade.commit()
|
||||||
|
|
||||||
rc = client_get(client, f"{BASE_URI}/trades/5/reload")
|
rc = client_post(client, f"{BASE_URI}/trades/5/reload")
|
||||||
assert ftbot.handle_onexchange_order.call_count == 1
|
assert ftbot.handle_onexchange_order.call_count == 1
|
||||||
|
|
||||||
|
|
||||||
@@ -888,8 +888,10 @@ def test_api_profit(botclient, mocker, ticker, fee, markets, is_short, expected)
|
|||||||
'best_pair_profit_ratio': expected['best_pair_profit_ratio'],
|
'best_pair_profit_ratio': expected['best_pair_profit_ratio'],
|
||||||
'best_rate': expected['best_rate'],
|
'best_rate': expected['best_rate'],
|
||||||
'first_trade_date': ANY,
|
'first_trade_date': ANY,
|
||||||
|
'first_trade_humanized': ANY,
|
||||||
'first_trade_timestamp': ANY,
|
'first_trade_timestamp': ANY,
|
||||||
'latest_trade_date': '5 minutes ago',
|
'latest_trade_date': ANY,
|
||||||
|
'latest_trade_humanized': '5 minutes ago',
|
||||||
'latest_trade_timestamp': ANY,
|
'latest_trade_timestamp': ANY,
|
||||||
'profit_all_coin': pytest.approx(expected['profit_all_coin']),
|
'profit_all_coin': pytest.approx(expected['profit_all_coin']),
|
||||||
'profit_all_fiat': pytest.approx(expected['profit_all_fiat']),
|
'profit_all_fiat': pytest.approx(expected['profit_all_fiat']),
|
||||||
@@ -1224,7 +1226,7 @@ def test_api_force_entry(botclient, mocker, fee, endpoint):
|
|||||||
stake_amount=1,
|
stake_amount=1,
|
||||||
open_rate=0.245441,
|
open_rate=0.245441,
|
||||||
open_order_id="123456",
|
open_order_id="123456",
|
||||||
open_date=datetime.utcnow(),
|
open_date=datetime.now(timezone.utc),
|
||||||
is_open=False,
|
is_open=False,
|
||||||
is_short=False,
|
is_short=False,
|
||||||
fee_close=fee.return_value,
|
fee_close=fee.return_value,
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ def default_conf(default_conf) -> dict:
|
|||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def update():
|
def update():
|
||||||
message = Message(0, datetime.utcnow(), Chat(0, 0))
|
message = Message(0, datetime.now(timezone.utc), Chat(0, 0))
|
||||||
_update = Update(0, message=message)
|
_update = Update(0, message=message)
|
||||||
|
|
||||||
return _update
|
return _update
|
||||||
@@ -213,7 +213,7 @@ async def test_authorized_only_unauthorized(default_conf, mocker, caplog) -> Non
|
|||||||
patch_exchange(mocker)
|
patch_exchange(mocker)
|
||||||
caplog.set_level(logging.DEBUG)
|
caplog.set_level(logging.DEBUG)
|
||||||
chat = Chat(0xdeadbeef, 0)
|
chat = Chat(0xdeadbeef, 0)
|
||||||
message = Message(randint(1, 100), datetime.utcnow(), chat)
|
message = Message(randint(1, 100), datetime.now(timezone.utc), chat)
|
||||||
update = Update(randint(1, 100), message=message)
|
update = Update(randint(1, 100), message=message)
|
||||||
|
|
||||||
default_conf['telegram']['enabled'] = False
|
default_conf['telegram']['enabled'] = False
|
||||||
@@ -520,7 +520,7 @@ async def test_daily_handle(default_conf_usdt, update, ticker, fee, mocker, time
|
|||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert "Daily Profit over the last 2 days</b>:" in msg_mock.call_args_list[0][0][0]
|
assert "Daily Profit over the last 2 days</b>:" in msg_mock.call_args_list[0][0][0]
|
||||||
assert 'Day ' in msg_mock.call_args_list[0][0][0]
|
assert 'Day ' 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(datetime.now(timezone.utc).date()) in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 6.83 USDT' in msg_mock.call_args_list[0][0][0]
|
assert ' 6.83 USDT' in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 7.51 USD' in msg_mock.call_args_list[0][0][0]
|
assert ' 7.51 USD' in msg_mock.call_args_list[0][0][0]
|
||||||
assert '(2)' in msg_mock.call_args_list[0][0][0]
|
assert '(2)' in msg_mock.call_args_list[0][0][0]
|
||||||
@@ -533,8 +533,9 @@ async def test_daily_handle(default_conf_usdt, update, ticker, fee, mocker, time
|
|||||||
await telegram._daily(update=update, context=context)
|
await telegram._daily(update=update, context=context)
|
||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert "Daily Profit over the last 7 days</b>:" in msg_mock.call_args_list[0][0][0]
|
assert "Daily Profit over the last 7 days</b>:" 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(datetime.now(timezone.utc).date()) in msg_mock.call_args_list[0][0][0]
|
||||||
assert str((datetime.utcnow() - timedelta(days=5)).date()) in msg_mock.call_args_list[0][0][0]
|
assert str((datetime.now(timezone.utc) - timedelta(days=5)).date()
|
||||||
|
) in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 6.83 USDT' in msg_mock.call_args_list[0][0][0]
|
assert ' 6.83 USDT' in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 7.51 USD' in msg_mock.call_args_list[0][0][0]
|
assert ' 7.51 USD' in msg_mock.call_args_list[0][0][0]
|
||||||
assert '(2)' in msg_mock.call_args_list[0][0][0]
|
assert '(2)' in msg_mock.call_args_list[0][0][0]
|
||||||
@@ -608,7 +609,7 @@ async def test_weekly_handle(default_conf_usdt, update, ticker, fee, mocker, tim
|
|||||||
assert "Weekly Profit over the last 2 weeks (starting from Monday)</b>:" \
|
assert "Weekly Profit over the last 2 weeks (starting from Monday)</b>:" \
|
||||||
in msg_mock.call_args_list[0][0][0]
|
in msg_mock.call_args_list[0][0][0]
|
||||||
assert 'Monday ' in msg_mock.call_args_list[0][0][0]
|
assert 'Monday ' in msg_mock.call_args_list[0][0][0]
|
||||||
today = datetime.utcnow().date()
|
today = datetime.now(timezone.utc).date()
|
||||||
first_iso_day_of_current_week = today - timedelta(days=today.weekday())
|
first_iso_day_of_current_week = today - timedelta(days=today.weekday())
|
||||||
assert str(first_iso_day_of_current_week) in msg_mock.call_args_list[0][0][0]
|
assert str(first_iso_day_of_current_week) in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 2.74 USDT' in msg_mock.call_args_list[0][0][0]
|
assert ' 2.74 USDT' in msg_mock.call_args_list[0][0][0]
|
||||||
@@ -677,7 +678,7 @@ async def test_monthly_handle(default_conf_usdt, update, ticker, fee, mocker, ti
|
|||||||
assert msg_mock.call_count == 1
|
assert msg_mock.call_count == 1
|
||||||
assert 'Monthly Profit over the last 2 months</b>:' in msg_mock.call_args_list[0][0][0]
|
assert 'Monthly Profit over the last 2 months</b>:' in msg_mock.call_args_list[0][0][0]
|
||||||
assert 'Month ' in msg_mock.call_args_list[0][0][0]
|
assert 'Month ' in msg_mock.call_args_list[0][0][0]
|
||||||
today = datetime.utcnow().date()
|
today = datetime.now(timezone.utc).date()
|
||||||
current_month = f"{today.year}-{today.month:02} "
|
current_month = f"{today.year}-{today.month:02} "
|
||||||
assert current_month in msg_mock.call_args_list[0][0][0]
|
assert current_month in msg_mock.call_args_list[0][0][0]
|
||||||
assert ' 2.74 USDT' in msg_mock.call_args_list[0][0][0]
|
assert ' 2.74 USDT' in msg_mock.call_args_list[0][0][0]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime, timezone
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from pandas import DataFrame
|
from pandas import DataFrame
|
||||||
@@ -43,12 +43,12 @@ def test_strategy_test_v3(dataframe_1m, fee, is_short, side):
|
|||||||
|
|
||||||
assert strategy.confirm_trade_entry(pair='ETH/BTC', order_type='limit', amount=0.1,
|
assert strategy.confirm_trade_entry(pair='ETH/BTC', order_type='limit', amount=0.1,
|
||||||
rate=20000, time_in_force='gtc',
|
rate=20000, time_in_force='gtc',
|
||||||
current_time=datetime.utcnow(),
|
current_time=datetime.now(timezone.utc),
|
||||||
side=side, entry_tag=None) is True
|
side=side, entry_tag=None) is True
|
||||||
assert strategy.confirm_trade_exit(pair='ETH/BTC', trade=trade, order_type='limit', amount=0.1,
|
assert strategy.confirm_trade_exit(pair='ETH/BTC', trade=trade, order_type='limit', amount=0.1,
|
||||||
rate=20000, time_in_force='gtc', exit_reason='roi',
|
rate=20000, time_in_force='gtc', exit_reason='roi',
|
||||||
sell_reason='roi',
|
sell_reason='roi',
|
||||||
current_time=datetime.utcnow(),
|
current_time=datetime.now(timezone.utc),
|
||||||
side=side) is True
|
side=side) is True
|
||||||
|
|
||||||
assert strategy.custom_stoploss(pair='ETH/BTC', trade=trade, current_time=datetime.now(),
|
assert strategy.custom_stoploss(pair='ETH/BTC', trade=trade, current_time=datetime.now(),
|
||||||
|
|||||||
Reference in New Issue
Block a user