updated mkdocs and leverage docs
Added tests for set_liquidation_price and set_stop_loss updated params in interestmode enum
This commit is contained in:
parent
f1dc6b54ad
commit
0d06d7e108
@ -1,3 +1,17 @@
|
||||
# Leverage
|
||||
|
||||
For shorts, the currency which pays the interest fee for the `borrowed` currency is purchased at the same time of the closing trade (This means that the amount purchased in short closing trades is greater than the amount sold in short opening trades).
|
||||
|
||||
For longs, the currency which pays the interest fee for the `borrowed` will already be owned by the user and does not need to be purchased. The interest is subtracted from the close_value of the trade.
|
||||
|
||||
## Binance margin trading interest formula
|
||||
|
||||
I (interest) = P (borrowed money) * R (daily_interest/24) * ceiling(T) (in hours)
|
||||
[source](https://www.binance.com/en/support/faq/360030157812)
|
||||
|
||||
## Kraken margin trading interest formula
|
||||
|
||||
Opening fee = P (borrowed money) * R (quat_hourly_interest)
|
||||
Rollover fee = P (borrowed money) * R (quat_hourly_interest) * ceiling(T/4) (in hours)
|
||||
I (interest) = Opening fee + Rollover fee
|
||||
[source](https://support.kraken.com/hc/en-us/articles/206161568-What-are-the-fees-for-margin-trading-)
|
||||
|
@ -17,14 +17,12 @@ class InterestMode(Enum):
|
||||
HOURSPER4 = "HOURSPER4" # Hours per 4 hour segment
|
||||
NONE = "NONE"
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
|
||||
borrowed, rate, hours = kwargs["borrowed"], kwargs["rate"], kwargs["hours"]
|
||||
def __call__(self, borrowed: Decimal, rate: Decimal, hours: Decimal):
|
||||
|
||||
if self.name == "HOURSPERDAY":
|
||||
return borrowed * rate * ceil(hours)/twenty_four
|
||||
elif self.name == "HOURSPER4":
|
||||
# Probably rounded based on https://kraken-fees-calculator.github.io/
|
||||
# Rounded based on https://kraken-fees-calculator.github.io/
|
||||
return borrowed * rate * (1+ceil(hours/four))
|
||||
else:
|
||||
raise OperationalException("Leverage not available on this exchange with freqtrade")
|
||||
|
@ -149,17 +149,16 @@ def migrate_orders_table(decl_base, inspector, engine, table_back_name: str, col
|
||||
# let SQLAlchemy create the schema as required
|
||||
decl_base.metadata.create_all(engine)
|
||||
leverage = get_column_def(cols, 'leverage', '1.0')
|
||||
is_short = get_column_def(cols, 'is_short', 'False')
|
||||
# TODO-mg: Should liquidation price go in here?
|
||||
# is_short = get_column_def(cols, 'is_short', 'False')
|
||||
|
||||
with engine.begin() as connection:
|
||||
connection.execute(text(f"""
|
||||
insert into orders ( id, ft_trade_id, ft_order_side, ft_pair, ft_is_open, order_id,
|
||||
status, symbol, order_type, side, price, amount, filled, average, remaining, cost,
|
||||
order_date, order_filled_date, order_update_date, leverage, is_short)
|
||||
order_date, order_filled_date, order_update_date, leverage)
|
||||
select id, ft_trade_id, ft_order_side, ft_pair, ft_is_open, order_id,
|
||||
status, symbol, order_type, side, price, amount, filled, null average, remaining, cost,
|
||||
order_date, order_filled_date, order_update_date,
|
||||
{leverage} leverage, {is_short} is_short
|
||||
order_date, order_filled_date, order_update_date, {leverage} leverage
|
||||
from {table_back_name}
|
||||
"""))
|
||||
|
||||
|
@ -133,7 +133,6 @@ class Order(_DECL_BASE):
|
||||
order_update_date = Column(DateTime, nullable=True)
|
||||
|
||||
leverage = Column(Float, nullable=True, default=1.0)
|
||||
is_short = Column(Boolean, nullable=True, default=False)
|
||||
|
||||
def __repr__(self):
|
||||
|
||||
@ -159,7 +158,7 @@ class Order(_DECL_BASE):
|
||||
self.remaining = order.get('remaining', self.remaining)
|
||||
self.cost = order.get('cost', self.cost)
|
||||
self.leverage = order.get('leverage', self.leverage)
|
||||
# TODO-mg: is_short?
|
||||
|
||||
if 'timestamp' in order and order['timestamp'] is not None:
|
||||
self.order_date = datetime.fromtimestamp(order['timestamp'] / 1000, tz=timezone.utc)
|
||||
|
||||
@ -301,44 +300,42 @@ class LocalTrade():
|
||||
def __init__(self, **kwargs):
|
||||
for key in kwargs:
|
||||
setattr(self, key, kwargs[key])
|
||||
self.set_liquidation_price(self.liquidation_price)
|
||||
if self.liquidation_price:
|
||||
self.set_liquidation_price(self.liquidation_price)
|
||||
self.recalc_open_trade_value()
|
||||
|
||||
def set_stop_loss_helper(self, stop_loss: Optional[float], liquidation_price: Optional[float]):
|
||||
"""Helper function for set_liquidation_price and set_stop_loss"""
|
||||
# Stoploss would be better as a computed variable,
|
||||
# but that messes up the database so it might not be possible
|
||||
|
||||
if liquidation_price is not None:
|
||||
if stop_loss is not None:
|
||||
if self.is_short:
|
||||
self.stop_loss = min(stop_loss, liquidation_price)
|
||||
else:
|
||||
self.stop_loss = max(stop_loss, liquidation_price)
|
||||
else:
|
||||
self.stop_loss = liquidation_price
|
||||
self.initial_stop_loss = liquidation_price
|
||||
self.liquidation_price = liquidation_price
|
||||
else:
|
||||
# programmming error check: 1 of liqudication_price or stop_loss must be set
|
||||
assert stop_loss is not None
|
||||
if not self.stop_loss:
|
||||
self.initial_stop_loss = stop_loss
|
||||
self.stop_loss = stop_loss
|
||||
|
||||
def set_stop_loss(self, stop_loss: float):
|
||||
"""
|
||||
Method you should use to set self.stop_loss.
|
||||
Assures stop_loss is not passed the liquidation price
|
||||
"""
|
||||
self.set_stop_loss_helper(stop_loss=stop_loss, liquidation_price=self.liquidation_price)
|
||||
if self.liquidation_price is not None:
|
||||
if self.is_short:
|
||||
sl = min(stop_loss, self.liquidation_price)
|
||||
else:
|
||||
sl = max(stop_loss, self.liquidation_price)
|
||||
else:
|
||||
sl = stop_loss
|
||||
|
||||
if not self.stop_loss:
|
||||
self.initial_stop_loss = sl
|
||||
self.stop_loss = sl
|
||||
|
||||
def set_liquidation_price(self, liquidation_price: float):
|
||||
"""
|
||||
Method you should use to set self.liquidation price.
|
||||
Assures stop_loss is not passed the liquidation price
|
||||
"""
|
||||
self.set_stop_loss_helper(stop_loss=self.stop_loss, liquidation_price=liquidation_price)
|
||||
if self.stop_loss is not None:
|
||||
if self.is_short:
|
||||
self.stop_loss = min(self.stop_loss, liquidation_price)
|
||||
else:
|
||||
self.stop_loss = max(self.stop_loss, liquidation_price)
|
||||
else:
|
||||
self.initial_stop_loss = liquidation_price
|
||||
self.stop_loss = liquidation_price
|
||||
|
||||
self.liquidation_price = liquidation_price
|
||||
|
||||
def __repr__(self):
|
||||
open_since = self.open_date.strftime(DATETIME_PRINT_FORMAT) if self.is_open else 'closed'
|
||||
|
87
mkdocs.yml
87
mkdocs.yml
@ -3,61 +3,62 @@ site_url: https://www.freqtrade.io/
|
||||
repo_url: https://github.com/freqtrade/freqtrade
|
||||
use_directory_urls: True
|
||||
nav:
|
||||
- Home: index.md
|
||||
- Quickstart with Docker: docker_quickstart.md
|
||||
- Installation:
|
||||
- Linux/MacOS/Raspberry: installation.md
|
||||
- Windows: windows_installation.md
|
||||
- Freqtrade Basics: bot-basics.md
|
||||
- Configuration: configuration.md
|
||||
- Strategy Customization: strategy-customization.md
|
||||
- Plugins: plugins.md
|
||||
- Stoploss: stoploss.md
|
||||
- Start the bot: bot-usage.md
|
||||
- Control the bot:
|
||||
- Telegram: telegram-usage.md
|
||||
- REST API & FreqUI: rest-api.md
|
||||
- Web Hook: webhook-config.md
|
||||
- Data Downloading: data-download.md
|
||||
- Backtesting: backtesting.md
|
||||
- Hyperopt: hyperopt.md
|
||||
- Utility Sub-commands: utils.md
|
||||
- Plotting: plotting.md
|
||||
- Data Analysis:
|
||||
- Jupyter Notebooks: data-analysis.md
|
||||
- Strategy analysis: strategy_analysis_example.md
|
||||
- Exchange-specific Notes: exchanges.md
|
||||
- Advanced Topics:
|
||||
- Advanced Post-installation Tasks: advanced-setup.md
|
||||
- Edge Positioning: edge.md
|
||||
- Advanced Strategy: strategy-advanced.md
|
||||
- Advanced Hyperopt: advanced-hyperopt.md
|
||||
- Sandbox Testing: sandbox-testing.md
|
||||
- FAQ: faq.md
|
||||
- SQL Cheat-sheet: sql_cheatsheet.md
|
||||
- Updating Freqtrade: updating.md
|
||||
- Deprecated Features: deprecated.md
|
||||
- Contributors Guide: developer.md
|
||||
- Home: index.md
|
||||
- Quickstart with Docker: docker_quickstart.md
|
||||
- Installation:
|
||||
- Linux/MacOS/Raspberry: installation.md
|
||||
- Windows: windows_installation.md
|
||||
- Freqtrade Basics: bot-basics.md
|
||||
- Configuration: configuration.md
|
||||
- Strategy Customization: strategy-customization.md
|
||||
- Plugins: plugins.md
|
||||
- Stoploss: stoploss.md
|
||||
- Start the bot: bot-usage.md
|
||||
- Control the bot:
|
||||
- Telegram: telegram-usage.md
|
||||
- REST API & FreqUI: rest-api.md
|
||||
- Web Hook: webhook-config.md
|
||||
- Data Downloading: data-download.md
|
||||
- Backtesting: backtesting.md
|
||||
- Leverage: leverage.md
|
||||
- Hyperopt: hyperopt.md
|
||||
- Utility Sub-commands: utils.md
|
||||
- Plotting: plotting.md
|
||||
- Data Analysis:
|
||||
- Jupyter Notebooks: data-analysis.md
|
||||
- Strategy analysis: strategy_analysis_example.md
|
||||
- Exchange-specific Notes: exchanges.md
|
||||
- Advanced Topics:
|
||||
- Advanced Post-installation Tasks: advanced-setup.md
|
||||
- Edge Positioning: edge.md
|
||||
- Advanced Strategy: strategy-advanced.md
|
||||
- Advanced Hyperopt: advanced-hyperopt.md
|
||||
- Sandbox Testing: sandbox-testing.md
|
||||
- FAQ: faq.md
|
||||
- SQL Cheat-sheet: sql_cheatsheet.md
|
||||
- Updating Freqtrade: updating.md
|
||||
- Deprecated Features: deprecated.md
|
||||
- Contributors Guide: developer.md
|
||||
theme:
|
||||
name: material
|
||||
logo: 'images/logo.png'
|
||||
favicon: 'images/logo.png'
|
||||
custom_dir: 'docs/overrides'
|
||||
logo: "images/logo.png"
|
||||
favicon: "images/logo.png"
|
||||
custom_dir: "docs/overrides"
|
||||
palette:
|
||||
- scheme: default
|
||||
primary: 'blue grey'
|
||||
accent: 'tear'
|
||||
primary: "blue grey"
|
||||
accent: "tear"
|
||||
toggle:
|
||||
icon: material/toggle-switch-off-outline
|
||||
name: Switch to dark mode
|
||||
- scheme: slate
|
||||
primary: 'blue grey'
|
||||
accent: 'tear'
|
||||
primary: "blue grey"
|
||||
accent: "tear"
|
||||
toggle:
|
||||
icon: material/toggle-switch-off-outline
|
||||
name: Switch to dark mode
|
||||
extra_css:
|
||||
- 'stylesheets/ft.extra.css'
|
||||
- "stylesheets/ft.extra.css"
|
||||
extra_javascript:
|
||||
- javascripts/config.js
|
||||
- https://polyfill.io/v3/polyfill.min.js?features=es6
|
||||
|
@ -418,6 +418,7 @@ def leverage_order_sell():
|
||||
'amount': 123.0,
|
||||
'filled': 123.0,
|
||||
'remaining': 0.0,
|
||||
'leverage': 5.0
|
||||
}
|
||||
|
||||
|
||||
|
@ -105,6 +105,85 @@ def test_is_opening_closing_trade(fee):
|
||||
assert trade.is_closing_trade('sell') is False
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("init_persistence")
|
||||
def test_set_stop_loss_liquidation_price(fee):
|
||||
trade = Trade(
|
||||
id=2,
|
||||
pair='ETH/BTC',
|
||||
stake_amount=0.001,
|
||||
open_rate=0.01,
|
||||
amount=5,
|
||||
is_open=True,
|
||||
open_date=arrow.utcnow().datetime,
|
||||
fee_open=fee.return_value,
|
||||
fee_close=fee.return_value,
|
||||
exchange='binance',
|
||||
is_short=False,
|
||||
leverage=2.0
|
||||
)
|
||||
trade.set_liquidation_price(0.09)
|
||||
assert trade.liquidation_price == 0.09
|
||||
assert trade.stop_loss == 0.09
|
||||
assert trade.initial_stop_loss == 0.09
|
||||
|
||||
trade.set_stop_loss(0.1)
|
||||
assert trade.liquidation_price == 0.09
|
||||
assert trade.stop_loss == 0.1
|
||||
assert trade.initial_stop_loss == 0.09
|
||||
|
||||
trade.set_liquidation_price(0.08)
|
||||
assert trade.liquidation_price == 0.08
|
||||
assert trade.stop_loss == 0.1
|
||||
assert trade.initial_stop_loss == 0.09
|
||||
|
||||
trade.set_liquidation_price(0.11)
|
||||
assert trade.liquidation_price == 0.11
|
||||
assert trade.stop_loss == 0.11
|
||||
assert trade.initial_stop_loss == 0.09
|
||||
|
||||
trade.set_stop_loss(0.1)
|
||||
assert trade.liquidation_price == 0.11
|
||||
assert trade.stop_loss == 0.11
|
||||
assert trade.initial_stop_loss == 0.09
|
||||
|
||||
trade.stop_loss = None
|
||||
trade.liquidation_price = None
|
||||
trade.initial_stop_loss = None
|
||||
trade.set_stop_loss(0.07)
|
||||
assert trade.liquidation_price is None
|
||||
assert trade.stop_loss == 0.07
|
||||
assert trade.initial_stop_loss == 0.07
|
||||
|
||||
trade.is_short = True
|
||||
trade.stop_loss = None
|
||||
trade.initial_stop_loss = None
|
||||
|
||||
trade.set_liquidation_price(0.09)
|
||||
assert trade.liquidation_price == 0.09
|
||||
assert trade.stop_loss == 0.09
|
||||
assert trade.initial_stop_loss == 0.09
|
||||
|
||||
trade.set_stop_loss(0.08)
|
||||
assert trade.liquidation_price == 0.09
|
||||
assert trade.stop_loss == 0.08
|
||||
assert trade.initial_stop_loss == 0.09
|
||||
|
||||
trade.set_liquidation_price(0.1)
|
||||
assert trade.liquidation_price == 0.1
|
||||
assert trade.stop_loss == 0.08
|
||||
assert trade.initial_stop_loss == 0.09
|
||||
|
||||
trade.set_liquidation_price(0.07)
|
||||
assert trade.liquidation_price == 0.07
|
||||
assert trade.stop_loss == 0.07
|
||||
assert trade.initial_stop_loss == 0.09
|
||||
|
||||
trade.set_stop_loss(0.1)
|
||||
assert trade.liquidation_price == 0.07
|
||||
assert trade.stop_loss == 0.07
|
||||
assert trade.initial_stop_loss == 0.09
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("init_persistence")
|
||||
def test_update_with_binance(limit_buy_order, limit_sell_order, fee, caplog):
|
||||
"""
|
||||
@ -729,7 +808,7 @@ def test_migrate_new(mocker, default_conf, fee, caplog):
|
||||
|
||||
assert orders[1].order_id == 'stop_order_id222'
|
||||
assert orders[1].ft_order_side == 'stoploss'
|
||||
assert orders[0].is_short is False
|
||||
# assert orders[0].is_short is False
|
||||
|
||||
|
||||
def test_migrate_mid_state(mocker, default_conf, fee, caplog):
|
||||
|
Loading…
Reference in New Issue
Block a user