Merge pull request #6670 from freqtrade/store_asset
store base and quote currency separately in the database
This commit is contained in:
commit
46c18dfce2
@ -341,15 +341,11 @@ class Exchange:
|
||||
return sorted(set([x['quote'] for _, x in markets.items()]))
|
||||
|
||||
def get_pair_quote_currency(self, pair: str) -> str:
|
||||
"""
|
||||
Return a pair's quote currency
|
||||
"""
|
||||
""" Return a pair's quote currency (base/quote:settlement) """
|
||||
return self.markets.get(pair, {}).get('quote', '')
|
||||
|
||||
def get_pair_base_currency(self, pair: str) -> str:
|
||||
"""
|
||||
Return a pair's base currency
|
||||
"""
|
||||
""" Return a pair's base currency (base/quote:settlement) """
|
||||
return self.markets.get(pair, {}).get('base', '')
|
||||
|
||||
def market_is_future(self, market: Dict[str, Any]) -> bool:
|
||||
|
@ -676,6 +676,7 @@ class FreqtradeBot(LoggingMixin):
|
||||
|
||||
# Fee is applied twice because we make a LIMIT_BUY and LIMIT_SELL
|
||||
fee = self.exchange.get_fee(symbol=pair, taker_or_maker='maker')
|
||||
base_currency = self.exchange.get_pair_base_currency(pair)
|
||||
open_date = datetime.now(timezone.utc)
|
||||
funding_fees = self.exchange.get_funding_fees(
|
||||
pair=pair, amount=amount, is_short=is_short, open_date=open_date)
|
||||
@ -683,6 +684,8 @@ class FreqtradeBot(LoggingMixin):
|
||||
if trade is None:
|
||||
trade = Trade(
|
||||
pair=pair,
|
||||
base_currency=base_currency,
|
||||
stake_currency=self.config['stake_currency'],
|
||||
stake_amount=stake_amount,
|
||||
amount=amount,
|
||||
is_open=True,
|
||||
|
@ -726,6 +726,7 @@ class Backtesting:
|
||||
|
||||
if stake_amount and (not min_stake_amount or stake_amount > min_stake_amount):
|
||||
self.order_id_counter += 1
|
||||
base_currency = self.exchange.get_pair_base_currency(pair)
|
||||
amount = round((stake_amount / propose_rate) * leverage, 8)
|
||||
is_short = (direction == 'short')
|
||||
# Necessary for Margin trading. Disabled until support is enabled.
|
||||
@ -738,6 +739,8 @@ class Backtesting:
|
||||
id=self.trade_id_counter,
|
||||
open_order_id=self.order_id_counter,
|
||||
pair=pair,
|
||||
base_currency=base_currency,
|
||||
stake_currency=self.config['stake_currency'],
|
||||
open_rate=propose_rate,
|
||||
open_rate_requested=propose_rate,
|
||||
open_date=current_time,
|
||||
|
@ -58,6 +58,8 @@ def migrate_trades_and_orders_table(
|
||||
decl_base, inspector, engine,
|
||||
trade_back_name: str, cols: List,
|
||||
order_back_name: str, cols_order: List):
|
||||
base_currency = get_column_def(cols, 'base_currency', 'null')
|
||||
stake_currency = get_column_def(cols, 'stake_currency', 'null')
|
||||
fee_open = get_column_def(cols, 'fee_open', 'fee')
|
||||
fee_open_cost = get_column_def(cols, 'fee_open_cost', 'null')
|
||||
fee_open_currency = get_column_def(cols, 'fee_open_currency', 'null')
|
||||
@ -130,7 +132,7 @@ def migrate_trades_and_orders_table(
|
||||
# Copy data back - following the correct schema
|
||||
with engine.begin() as connection:
|
||||
connection.execute(text(f"""insert into trades
|
||||
(id, exchange, pair, is_open,
|
||||
(id, exchange, pair, base_currency, stake_currency, is_open,
|
||||
fee_open, fee_open_cost, fee_open_currency,
|
||||
fee_close, fee_close_cost, fee_close_currency, open_rate,
|
||||
open_rate_requested, close_rate, close_rate_requested, close_profit,
|
||||
@ -142,7 +144,8 @@ def migrate_trades_and_orders_table(
|
||||
trading_mode, leverage, liquidation_price, is_short,
|
||||
interest_rate, funding_fees
|
||||
)
|
||||
select id, lower(exchange), pair,
|
||||
select id, lower(exchange), pair, {base_currency} base_currency,
|
||||
{stake_currency} stake_currency,
|
||||
is_open, {fee_open} fee_open, {fee_open_cost} fee_open_cost,
|
||||
{fee_open_currency} fee_open_currency, {fee_close} fee_close,
|
||||
{fee_close_cost} fee_close_cost, {fee_close_currency} fee_close_currency,
|
||||
@ -230,7 +233,7 @@ def check_migrate(engine, decl_base, previous_tables) -> None:
|
||||
"""
|
||||
inspector = inspect(engine)
|
||||
|
||||
cols = inspector.get_columns('trades')
|
||||
cols_trades = inspector.get_columns('trades')
|
||||
cols_orders = inspector.get_columns('orders')
|
||||
tabs = get_table_names_for_table(inspector, 'trades')
|
||||
table_back_name = get_backup_name(tabs, 'trades_bak')
|
||||
@ -241,11 +244,12 @@ def check_migrate(engine, decl_base, previous_tables) -> None:
|
||||
# Migrates both trades and orders table!
|
||||
# if ('orders' not in previous_tables
|
||||
# or not has_column(cols_orders, 'leverage')):
|
||||
if not has_column(cols, 'exit_order_status'):
|
||||
if not has_column(cols_trades, 'base_currency'):
|
||||
logger.info(f"Running database migration for trades - "
|
||||
f"backup: {table_back_name}, {order_table_bak_name}")
|
||||
migrate_trades_and_orders_table(
|
||||
decl_base, inspector, engine, table_back_name, cols, order_table_bak_name, cols_orders)
|
||||
decl_base, inspector, engine, table_back_name, cols_trades,
|
||||
order_table_bak_name, cols_orders)
|
||||
|
||||
if 'orders' not in previous_tables and 'trades' in previous_tables:
|
||||
logger.info('Moving open orders to Orders table.')
|
||||
|
@ -279,6 +279,8 @@ class LocalTrade():
|
||||
|
||||
exchange: str = ''
|
||||
pair: str = ''
|
||||
base_currency: str = ''
|
||||
stake_currency: str = ''
|
||||
is_open: bool = True
|
||||
fee_open: float = 0.0
|
||||
fee_open_cost: Optional[float] = None
|
||||
@ -397,6 +399,26 @@ class LocalTrade():
|
||||
else:
|
||||
return "long"
|
||||
|
||||
@property
|
||||
def safe_base_currency(self) -> str:
|
||||
"""
|
||||
Compatibility layer for asset - which can be empty for old trades.
|
||||
"""
|
||||
try:
|
||||
return self.base_currency or self.pair.split('/')[0]
|
||||
except IndexError:
|
||||
return ''
|
||||
|
||||
@property
|
||||
def safe_quote_currency(self) -> str:
|
||||
"""
|
||||
Compatibility layer for asset - which can be empty for old trades.
|
||||
"""
|
||||
try:
|
||||
return self.stake_currency or self.pair.split('/')[1].split(':')[0]
|
||||
except IndexError:
|
||||
return ''
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
for key in kwargs:
|
||||
setattr(self, key, kwargs[key])
|
||||
@ -423,6 +445,8 @@ class LocalTrade():
|
||||
return {
|
||||
'trade_id': self.id,
|
||||
'pair': self.pair,
|
||||
'base_currency': self.safe_base_currency,
|
||||
'quote_currency': self.safe_quote_currency,
|
||||
'is_open': self.is_open,
|
||||
'exchange': self.exchange,
|
||||
'amount': round(self.amount, 8),
|
||||
@ -1051,6 +1075,8 @@ class Trade(_DECL_BASE, LocalTrade):
|
||||
|
||||
exchange = Column(String(25), nullable=False)
|
||||
pair = Column(String(25), nullable=False, index=True)
|
||||
base_currency = Column(String(25), nullable=True)
|
||||
stake_currency = Column(String(25), nullable=True)
|
||||
is_open = Column(Boolean, nullable=False, default=True, index=True)
|
||||
fee_open = Column(Float, nullable=False, default=0.0)
|
||||
fee_open_cost = Column(Float, nullable=True)
|
||||
|
@ -203,6 +203,8 @@ class OrderSchema(BaseModel):
|
||||
class TradeSchema(BaseModel):
|
||||
trade_id: int
|
||||
pair: str
|
||||
base_currency: str
|
||||
quote_currency: str
|
||||
is_open: bool
|
||||
is_short: bool
|
||||
exchange: str
|
||||
|
@ -197,7 +197,6 @@ class RPC:
|
||||
|
||||
trade_dict = trade.to_json()
|
||||
trade_dict.update(dict(
|
||||
base_currency=self._freqtrade.config['stake_currency'],
|
||||
close_profit=trade.close_profit if trade.close_profit is not None else None,
|
||||
current_rate=current_rate,
|
||||
current_profit=current_profit, # Deprecated
|
||||
|
@ -508,7 +508,7 @@ class Telegram(RPCHandler):
|
||||
lines.append("*Open Order:* `{open_order}`")
|
||||
|
||||
lines_detail = self._prepare_entry_details(
|
||||
r['orders'], r['base_currency'], r['is_open'])
|
||||
r['orders'], r['quote_currency'], r['is_open'])
|
||||
lines.extend(lines_detail if lines_detail else "")
|
||||
|
||||
# Filter empty lines using list-comprehension
|
||||
|
@ -52,7 +52,8 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
|
||||
assert results[0] == {
|
||||
'trade_id': 1,
|
||||
'pair': 'ETH/BTC',
|
||||
'base_currency': 'BTC',
|
||||
'base_currency': 'ETH',
|
||||
'quote_currency': 'BTC',
|
||||
'open_date': ANY,
|
||||
'open_timestamp': ANY,
|
||||
'is_open': ANY,
|
||||
@ -135,7 +136,8 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
|
||||
assert results[0] == {
|
||||
'trade_id': 1,
|
||||
'pair': 'ETH/BTC',
|
||||
'base_currency': 'BTC',
|
||||
'base_currency': 'ETH',
|
||||
'quote_currency': 'BTC',
|
||||
'open_date': ANY,
|
||||
'open_timestamp': ANY,
|
||||
'is_open': ANY,
|
||||
|
@ -931,6 +931,8 @@ def test_api_status(botclient, mocker, ticker, fee, markets, is_short,
|
||||
'open_order': None,
|
||||
'open_rate': 0.123,
|
||||
'pair': 'ETH/BTC',
|
||||
'base_currency': 'ETH',
|
||||
'quote_currency': 'BTC',
|
||||
'stake_amount': 0.001,
|
||||
'stop_loss_abs': ANY,
|
||||
'stop_loss_pct': ANY,
|
||||
@ -1097,7 +1099,7 @@ def test_api_force_entry(botclient, mocker, fee, endpoint):
|
||||
|
||||
# Test creating trade
|
||||
fbuy_mock = MagicMock(return_value=Trade(
|
||||
pair='ETH/ETH',
|
||||
pair='ETH/BTC',
|
||||
amount=1,
|
||||
amount_requested=1,
|
||||
exchange='binance',
|
||||
@ -1130,7 +1132,9 @@ def test_api_force_entry(botclient, mocker, fee, endpoint):
|
||||
'open_date': ANY,
|
||||
'open_timestamp': ANY,
|
||||
'open_rate': 0.245441,
|
||||
'pair': 'ETH/ETH',
|
||||
'pair': 'ETH/BTC',
|
||||
'base_currency': 'ETH',
|
||||
'quote_currency': 'BTC',
|
||||
'stake_amount': 1,
|
||||
'stop_loss_abs': None,
|
||||
'stop_loss_pct': None,
|
||||
|
@ -184,7 +184,8 @@ def test_telegram_status(default_conf, update, mocker) -> None:
|
||||
_rpc_trade_status=MagicMock(return_value=[{
|
||||
'trade_id': 1,
|
||||
'pair': 'ETH/BTC',
|
||||
'base_currency': 'BTC',
|
||||
'base_currency': 'ETH',
|
||||
'quote_currency': 'BTC',
|
||||
'open_date': arrow.utcnow(),
|
||||
'close_date': None,
|
||||
'open_rate': 1.099e-05,
|
||||
|
@ -1561,6 +1561,8 @@ def test_to_json(fee):
|
||||
|
||||
assert result == {'trade_id': None,
|
||||
'pair': 'ADA/USDT',
|
||||
'base_currency': 'ADA',
|
||||
'quote_currency': 'USDT',
|
||||
'is_open': None,
|
||||
'open_date': trade.open_date.strftime("%Y-%m-%d %H:%M:%S"),
|
||||
'open_timestamp': int(trade.open_date.timestamp() * 1000),
|
||||
@ -1637,6 +1639,8 @@ def test_to_json(fee):
|
||||
|
||||
assert result == {'trade_id': None,
|
||||
'pair': 'XRP/BTC',
|
||||
'base_currency': 'XRP',
|
||||
'quote_currency': 'BTC',
|
||||
'open_date': trade.open_date.strftime("%Y-%m-%d %H:%M:%S"),
|
||||
'open_timestamp': int(trade.open_date.timestamp() * 1000),
|
||||
'close_date': trade.close_date.strftime("%Y-%m-%d %H:%M:%S"),
|
||||
|
Loading…
Reference in New Issue
Block a user