commit
64917275a9
@ -28,8 +28,6 @@ Regular trading mode (low risk)
|
|||||||
|
|
||||||
### Leverage trading modes
|
### Leverage trading modes
|
||||||
|
|
||||||
# TODO-lev: include a resource to help calculate stoplosses that are above the liquidation price
|
|
||||||
|
|
||||||
With leverage, a trader borrows capital from the exchange. The capital must be repayed fully to the exchange(potentially with interest), and the trader keeps any profits, or pays any losses, from any trades made using the borrowed capital.
|
With leverage, a trader borrows capital from the exchange. The capital must be repayed fully to the exchange(potentially with interest), and the trader keeps any profits, or pays any losses, from any trades made using the borrowed capital.
|
||||||
|
|
||||||
Because the capital must always be repayed, exchanges will **liquidate** a trade (forcefully sell the traders assets) made using borrowed capital when the total value of assets in a leverage account drops to a certain point(a point where the total value of losses is less than the value of the collateral that the trader actually owns in the leverage account), in order to ensure that the trader has enough capital to pay back the borrowed assets to the exchange. The exchange will also charge a **liquidation fee**, adding to the traders losses. For this reason, **DO NOT TRADE WITH LEVERAGE IF YOU DON'T KNOW EXACTLY WHAT YOUR DOING. LEVERAGE TRADING IS HIGH RISK, AND CAN RESULT IN THE VALUE OF YOUR ASSETS DROPPING TO 0 VERY QUICKLY, WITH NO CHANCE OF INCREASING IN VALUE AGAIN**
|
Because the capital must always be repayed, exchanges will **liquidate** a trade (forcefully sell the traders assets) made using borrowed capital when the total value of assets in a leverage account drops to a certain point(a point where the total value of losses is less than the value of the collateral that the trader actually owns in the leverage account), in order to ensure that the trader has enough capital to pay back the borrowed assets to the exchange. The exchange will also charge a **liquidation fee**, adding to the traders losses. For this reason, **DO NOT TRADE WITH LEVERAGE IF YOU DON'T KNOW EXACTLY WHAT YOUR DOING. LEVERAGE TRADING IS HIGH RISK, AND CAN RESULT IN THE VALUE OF YOUR ASSETS DROPPING TO 0 VERY QUICKLY, WITH NO CHANCE OF INCREASING IN VALUE AGAIN**
|
||||||
|
@ -102,4 +102,3 @@ def start_hyperopt_show(args: Dict[str, Any]) -> None:
|
|||||||
|
|
||||||
HyperoptTools.show_epoch_details(val, total_epochs, print_json, no_header,
|
HyperoptTools.show_epoch_details(val, total_epochs, print_json, no_header,
|
||||||
header_str="Epoch details")
|
header_str="Epoch details")
|
||||||
# TODO-lev: Hyperopt optimal leverage
|
|
||||||
|
@ -224,7 +224,6 @@ class Binance(Exchange):
|
|||||||
|
|
||||||
def funding_fee_cutoff(self, open_date: datetime):
|
def funding_fee_cutoff(self, open_date: datetime):
|
||||||
"""
|
"""
|
||||||
# TODO-lev: Double check that gateio, ftx, and kraken don't also have this
|
|
||||||
:param open_date: The open date for a trade
|
:param open_date: The open date for a trade
|
||||||
:return: The cutoff open time for when a funding fee is charged
|
:return: The cutoff open time for when a funding fee is charged
|
||||||
"""
|
"""
|
||||||
|
@ -80,7 +80,6 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
# so anything in the Freqtradebot instance should be ready (initialized), including
|
# so anything in the Freqtradebot instance should be ready (initialized), including
|
||||||
# the initial state of the bot.
|
# the initial state of the bot.
|
||||||
# Keep this at the end of this initialization method.
|
# Keep this at the end of this initialization method.
|
||||||
# TODO-lev: Do I need to consider the rpc, pairlists or dataprovider?
|
|
||||||
self.rpc: RPCManager = RPCManager(self)
|
self.rpc: RPCManager = RPCManager(self)
|
||||||
|
|
||||||
self.pairlists = PairListManager(self.exchange, self.config)
|
self.pairlists = PairListManager(self.exchange, self.config)
|
||||||
|
@ -335,7 +335,9 @@ class LocalTrade():
|
|||||||
if self.isolated_liq:
|
if self.isolated_liq:
|
||||||
self.set_isolated_liq(self.isolated_liq)
|
self.set_isolated_liq(self.isolated_liq)
|
||||||
self.recalc_open_trade_value()
|
self.recalc_open_trade_value()
|
||||||
# TODO-lev: Throw exception if on margin and interest_rate is none
|
if self.trading_mode == TradingMode.MARGIN and self.interest_rate is None:
|
||||||
|
raise OperationalException(
|
||||||
|
f"{self.trading_mode.value} trading requires param interest_rate on trades")
|
||||||
|
|
||||||
def _set_stop_loss(self, stop_loss: float, percent: float):
|
def _set_stop_loss(self, stop_loss: float, percent: float):
|
||||||
"""
|
"""
|
||||||
|
@ -128,7 +128,6 @@ class PairListManager():
|
|||||||
:return: pairlist - whitelisted pairs
|
:return: pairlist - whitelisted pairs
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
# TODO-lev: filter for pairlists that are able to trade at the desired leverage
|
|
||||||
whitelist = expand_pairlist(pairlist, self._exchange.get_markets().keys(), keep_invalid)
|
whitelist = expand_pairlist(pairlist, self._exchange.get_markets().keys(), keep_invalid)
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
logger.error(f"Pair whitelist contains an invalid Wildcard: {err}")
|
logger.error(f"Pair whitelist contains an invalid Wildcard: {err}")
|
||||||
|
@ -36,8 +36,7 @@ class MaxDrawdown(IProtection):
|
|||||||
"""
|
"""
|
||||||
LockReason to use
|
LockReason to use
|
||||||
"""
|
"""
|
||||||
# TODO-lev: < for shorts?
|
return (f'{drawdown} passed {self._max_allowed_drawdown} in {self.lookback_period_str}, '
|
||||||
return (f'{drawdown} > {self._max_allowed_drawdown} in {self.lookback_period_str}, '
|
|
||||||
f'locking for {self.stop_duration_str}.')
|
f'locking for {self.stop_duration_str}.')
|
||||||
|
|
||||||
def _max_drawdown(self, date_now: datetime) -> ProtectionReturn:
|
def _max_drawdown(self, date_now: datetime) -> ProtectionReturn:
|
||||||
|
@ -32,7 +32,6 @@ class StoplossGuard(IProtection):
|
|||||||
def _reason(self) -> str:
|
def _reason(self) -> str:
|
||||||
"""
|
"""
|
||||||
LockReason to use
|
LockReason to use
|
||||||
# TODO-lev: check if min is the right word for shorts
|
|
||||||
"""
|
"""
|
||||||
return (f'{self._trade_limit} stoplosses in {self._lookback_period} min, '
|
return (f'{self._trade_limit} stoplosses in {self._lookback_period} min, '
|
||||||
f'locking for {self._stop_duration} min.')
|
f'locking for {self._stop_duration} min.')
|
||||||
|
@ -39,7 +39,6 @@ class RPCException(Exception):
|
|||||||
|
|
||||||
raise RPCException('*Status:* `no active trade`')
|
raise RPCException('*Status:* `no active trade`')
|
||||||
"""
|
"""
|
||||||
# TODO-lev: Add new configuration options introduced with leveraged/short trading
|
|
||||||
|
|
||||||
def __init__(self, message: str) -> None:
|
def __init__(self, message: str) -> None:
|
||||||
super().__init__(self)
|
super().__init__(self)
|
||||||
|
@ -1294,7 +1294,6 @@ class Telegram(RPCHandler):
|
|||||||
" *table :* `will display trades in a table`\n"
|
" *table :* `will display trades in a table`\n"
|
||||||
" `pending buy orders are marked with an asterisk (*)`\n"
|
" `pending buy orders are marked with an asterisk (*)`\n"
|
||||||
" `pending sell orders are marked with a double asterisk (**)`\n"
|
" `pending sell orders are marked with a double asterisk (**)`\n"
|
||||||
# TODO-lev: Update commands and help (?)
|
|
||||||
"*/buys <pair|none>:* `Shows the enter_tag performance`\n"
|
"*/buys <pair|none>:* `Shows the enter_tag performance`\n"
|
||||||
"*/sells <pair|none>:* `Shows the sell reason performance`\n"
|
"*/sells <pair|none>:* `Shows the sell reason performance`\n"
|
||||||
"*/mix_tags <pair|none>:* `Shows combined buy tag + sell reason performance`\n"
|
"*/mix_tags <pair|none>:* `Shows combined buy tag + sell reason performance`\n"
|
||||||
|
@ -1667,8 +1667,8 @@ def test_get_historic_ohlcv_as_df(default_conf, mocker, exchange_name, candle_ty
|
|||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
@pytest.mark.parametrize("exchange_name", EXCHANGES)
|
@pytest.mark.parametrize("exchange_name", EXCHANGES)
|
||||||
# TODO-lev @pytest.mark.parametrize('candle_type', ['mark', ''])
|
@pytest.mark.parametrize('candle_type', [CandleType.MARK, CandleType.SPOT])
|
||||||
async def test__async_get_historic_ohlcv(default_conf, mocker, caplog, exchange_name):
|
async def test__async_get_historic_ohlcv(default_conf, mocker, caplog, exchange_name, candle_type):
|
||||||
ohlcv = [
|
ohlcv = [
|
||||||
[
|
[
|
||||||
int((datetime.now(timezone.utc).timestamp() - 1000) * 1000),
|
int((datetime.now(timezone.utc).timestamp() - 1000) * 1000),
|
||||||
@ -1685,7 +1685,7 @@ async def test__async_get_historic_ohlcv(default_conf, mocker, caplog, exchange_
|
|||||||
|
|
||||||
pair = 'ETH/USDT'
|
pair = 'ETH/USDT'
|
||||||
respair, restf, _, res = await exchange._async_get_historic_ohlcv(
|
respair, restf, _, res = await exchange._async_get_historic_ohlcv(
|
||||||
pair, "5m", 1500000000000, candle_type=CandleType.SPOT, is_new_pair=False)
|
pair, "5m", 1500000000000, candle_type=candle_type, is_new_pair=False)
|
||||||
assert respair == pair
|
assert respair == pair
|
||||||
assert restf == '5m'
|
assert restf == '5m'
|
||||||
# Call with very old timestamp - causes tons of requests
|
# Call with very old timestamp - causes tons of requests
|
||||||
|
@ -164,8 +164,6 @@ def test_get_balances_prod(default_conf, mocker):
|
|||||||
ccxt_exceptionhandlers(mocker, default_conf, api_mock, "kraken",
|
ccxt_exceptionhandlers(mocker, default_conf, api_mock, "kraken",
|
||||||
"get_balances", "fetch_balance")
|
"get_balances", "fetch_balance")
|
||||||
|
|
||||||
# TODO-lev: All these stoploss tests with shorts
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('ordertype', ['market', 'limit'])
|
@pytest.mark.parametrize('ordertype', ['market', 'limit'])
|
||||||
@pytest.mark.parametrize('side,adjustedprice', [
|
@pytest.mark.parametrize('side,adjustedprice', [
|
||||||
|
@ -710,8 +710,8 @@ def test_process_informative_pairs_added(default_conf_usdt, ticker_usdt, mocker)
|
|||||||
'spot',
|
'spot',
|
||||||
# TODO-lev: Enable other modes
|
# TODO-lev: Enable other modes
|
||||||
# 'margin', 'futures'
|
# 'margin', 'futures'
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
@pytest.mark.parametrize("is_short", [False, True])
|
@pytest.mark.parametrize("is_short", [False, True])
|
||||||
def test_execute_entry(mocker, default_conf_usdt, fee, limit_order,
|
def test_execute_entry(mocker, default_conf_usdt, fee, limit_order,
|
||||||
limit_order_open, is_short, trading_mode) -> None:
|
limit_order_open, is_short, trading_mode) -> None:
|
||||||
@ -2090,9 +2090,8 @@ def test_handle_trade_roi(default_conf_usdt, ticker_usdt, limit_order_open, fee,
|
|||||||
# we might just want to check if we are in a sell condition without
|
# we might just want to check if we are in a sell condition without
|
||||||
# executing
|
# executing
|
||||||
# if ROI is reached we must sell
|
# if ROI is reached we must sell
|
||||||
# TODO-lev: Change the next line for shorts
|
|
||||||
caplog.clear()
|
caplog.clear()
|
||||||
patch_get_signal(freqtrade, enter_long=False, exit_long=True)
|
patch_get_signal(freqtrade, enter_long=False, exit_long=not is_short, exit_short=is_short)
|
||||||
assert freqtrade.handle_trade(trade)
|
assert freqtrade.handle_trade(trade)
|
||||||
assert log_has("ETH/USDT - Required profit reached. sell_type=SellType.ROI",
|
assert log_has("ETH/USDT - Required profit reached. sell_type=SellType.ROI",
|
||||||
caplog)
|
caplog)
|
||||||
|
Loading…
Reference in New Issue
Block a user