Introduce Order database model
This commit is contained in:
parent
7d03a067ee
commit
171a52b21a
@ -487,6 +487,7 @@ class Exchange:
|
|||||||
'side': side,
|
'side': side,
|
||||||
'remaining': _amount,
|
'remaining': _amount,
|
||||||
'datetime': arrow.utcnow().isoformat(),
|
'datetime': arrow.utcnow().isoformat(),
|
||||||
|
'timestamp': arrow.utcnow().timestamp,
|
||||||
'status': "closed" if ordertype == "market" else "open",
|
'status': "closed" if ordertype == "market" else "open",
|
||||||
'fee': None,
|
'fee': None,
|
||||||
'info': {}
|
'info': {}
|
||||||
|
@ -22,7 +22,7 @@ from freqtrade.exceptions import (DependencyException, ExchangeError,
|
|||||||
from freqtrade.exchange import timeframe_to_minutes, timeframe_to_next_date
|
from freqtrade.exchange import timeframe_to_minutes, timeframe_to_next_date
|
||||||
from freqtrade.misc import safe_value_fallback, safe_value_fallback2
|
from freqtrade.misc import safe_value_fallback, safe_value_fallback2
|
||||||
from freqtrade.pairlist.pairlistmanager import PairListManager
|
from freqtrade.pairlist.pairlistmanager import PairListManager
|
||||||
from freqtrade.persistence import Trade
|
from freqtrade.persistence import Order, Trade
|
||||||
from freqtrade.resolvers import ExchangeResolver, StrategyResolver
|
from freqtrade.resolvers import ExchangeResolver, StrategyResolver
|
||||||
from freqtrade.rpc import RPCManager, RPCMessageType
|
from freqtrade.rpc import RPCManager, RPCMessageType
|
||||||
from freqtrade.state import State
|
from freqtrade.state import State
|
||||||
@ -527,6 +527,7 @@ class FreqtradeBot:
|
|||||||
order = self.exchange.buy(pair=pair, ordertype=order_type,
|
order = self.exchange.buy(pair=pair, ordertype=order_type,
|
||||||
amount=amount, rate=buy_limit_requested,
|
amount=amount, rate=buy_limit_requested,
|
||||||
time_in_force=time_in_force)
|
time_in_force=time_in_force)
|
||||||
|
order_obj = Order.parse_from_ccxt_object(order, pair)
|
||||||
order_id = order['id']
|
order_id = order['id']
|
||||||
order_status = order.get('status', None)
|
order_status = order.get('status', None)
|
||||||
|
|
||||||
@ -580,6 +581,7 @@ class FreqtradeBot:
|
|||||||
strategy=self.strategy.get_strategy_name(),
|
strategy=self.strategy.get_strategy_name(),
|
||||||
timeframe=timeframe_to_minutes(self.config['timeframe'])
|
timeframe=timeframe_to_minutes(self.config['timeframe'])
|
||||||
)
|
)
|
||||||
|
trade.orders.append(order_obj)
|
||||||
|
|
||||||
# Update fees if order is closed
|
# Update fees if order is closed
|
||||||
if order_status == 'closed':
|
if order_status == 'closed':
|
||||||
@ -781,6 +783,9 @@ class FreqtradeBot:
|
|||||||
stoploss_order = self.exchange.stoploss(pair=trade.pair, amount=trade.amount,
|
stoploss_order = self.exchange.stoploss(pair=trade.pair, amount=trade.amount,
|
||||||
stop_price=stop_price,
|
stop_price=stop_price,
|
||||||
order_types=self.strategy.order_types)
|
order_types=self.strategy.order_types)
|
||||||
|
|
||||||
|
order_obj = Order.parse_from_ccxt_object(stoploss_order, trade.pair)
|
||||||
|
trade.orders.append(order_obj)
|
||||||
trade.stoploss_order_id = str(stoploss_order['id'])
|
trade.stoploss_order_id = str(stoploss_order['id'])
|
||||||
return True
|
return True
|
||||||
except InvalidOrderException as e:
|
except InvalidOrderException as e:
|
||||||
@ -1123,12 +1128,15 @@ class FreqtradeBot:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
# Execute sell and update trade record
|
# Execute sell and update trade record
|
||||||
order = self.exchange.sell(pair=str(trade.pair),
|
order = self.exchange.sell(pair=trade.pair,
|
||||||
ordertype=order_type,
|
ordertype=order_type,
|
||||||
amount=amount, rate=limit,
|
amount=amount, rate=limit,
|
||||||
time_in_force=time_in_force
|
time_in_force=time_in_force
|
||||||
)
|
)
|
||||||
|
|
||||||
|
order_obj = Order.parse_from_ccxt_object(order, trade.pair)
|
||||||
|
trade.orders.append(order_obj)
|
||||||
|
|
||||||
trade.open_order_id = order['id']
|
trade.open_order_id = order['id']
|
||||||
trade.close_rate_requested = limit
|
trade.close_rate_requested = limit
|
||||||
trade.sell_reason = sell_reason.value
|
trade.sell_reason = sell_reason.value
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
# flake8: noqa: F401
|
# flake8: noqa: F401
|
||||||
|
|
||||||
from freqtrade.persistence.models import Trade, clean_dry_run_db, cleanup, init
|
from freqtrade.persistence.models import (Order, Trade, clean_dry_run_db,
|
||||||
|
cleanup, init)
|
||||||
|
@ -7,11 +7,11 @@ from decimal import Decimal
|
|||||||
from typing import Any, Dict, List, Optional
|
from typing import Any, Dict, List, Optional
|
||||||
|
|
||||||
import arrow
|
import arrow
|
||||||
from sqlalchemy import (Boolean, Column, DateTime, Float, Integer, String,
|
from sqlalchemy import (Boolean, Column, DateTime, Float, Integer, String, ForeignKey,
|
||||||
create_engine, desc, func)
|
create_engine, desc, func)
|
||||||
from sqlalchemy.exc import NoSuchModuleError
|
from sqlalchemy.exc import NoSuchModuleError
|
||||||
from sqlalchemy.ext.declarative import declarative_base
|
from sqlalchemy.ext.declarative import declarative_base
|
||||||
from sqlalchemy.orm import Query
|
from sqlalchemy.orm import Query, relationship
|
||||||
from sqlalchemy.orm.scoping import scoped_session
|
from sqlalchemy.orm.scoping import scoped_session
|
||||||
from sqlalchemy.orm.session import sessionmaker
|
from sqlalchemy.orm.session import sessionmaker
|
||||||
from sqlalchemy.pool import StaticPool
|
from sqlalchemy.pool import StaticPool
|
||||||
@ -85,13 +85,71 @@ def clean_dry_run_db() -> None:
|
|||||||
trade.open_order_id = None
|
trade.open_order_id = None
|
||||||
|
|
||||||
|
|
||||||
|
class Order(_DECL_BASE):
|
||||||
|
"""
|
||||||
|
Order database model
|
||||||
|
Keeps a record of all orders placed on the exchange
|
||||||
|
|
||||||
|
One to many relationship with Trades:
|
||||||
|
- One trade can have many orders
|
||||||
|
- One Order can only be associated with one Trade
|
||||||
|
|
||||||
|
Mirrors CCXT Order structure
|
||||||
|
"""
|
||||||
|
__tablename__ = 'orders'
|
||||||
|
|
||||||
|
id = Column(Integer, primary_key=True)
|
||||||
|
trade_id = Column(Integer, ForeignKey('trades.id'), index=True)
|
||||||
|
|
||||||
|
order_id = Column(String, nullable=False, index=True)
|
||||||
|
status = Column(String, nullable=False)
|
||||||
|
symbol = Column(String, nullable=False)
|
||||||
|
order_type = Column(String, nullable=False)
|
||||||
|
side = Column(String, nullable=False)
|
||||||
|
price = Column(Float, nullable=False)
|
||||||
|
amount = Column(Float, nullable=False)
|
||||||
|
filled = Column(Float, nullable=True)
|
||||||
|
remaining = Column(Float, nullable=True)
|
||||||
|
cost = Column(Float, nullable=True)
|
||||||
|
order_date = Column(DateTime, nullable=False, default=datetime.utcnow)
|
||||||
|
order_filled_date = Column(DateTime, nullable=True)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def parse_from_ccxt_object(order, pair) -> 'Order':
|
||||||
|
"""
|
||||||
|
Parse an order from a ccxt object and return a new order Object.
|
||||||
|
"""
|
||||||
|
o = Order(order_id=str(order['id']))
|
||||||
|
|
||||||
|
o.status = order['status']
|
||||||
|
o.symbol = order.get('symbol', pair)
|
||||||
|
o.order_type = order['type']
|
||||||
|
o.side = order['side']
|
||||||
|
o.price = order['price']
|
||||||
|
o.amount = order['amount']
|
||||||
|
o.filled = order.get('filled')
|
||||||
|
o.remaining = order.get('remaining')
|
||||||
|
o.cost = order.get('cost')
|
||||||
|
o.order_date = datetime.fromtimestamp(order['timestamp'])
|
||||||
|
return o
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
|
||||||
|
return (f'Order(id={self.id}, trade_id={self.trade_id}, side={self.side}, '
|
||||||
|
f'status={self.status})')
|
||||||
|
|
||||||
|
|
||||||
class Trade(_DECL_BASE):
|
class Trade(_DECL_BASE):
|
||||||
"""
|
"""
|
||||||
Class used to define a trade structure
|
Trade database model.
|
||||||
|
Also handles updating and querying trades
|
||||||
"""
|
"""
|
||||||
__tablename__ = 'trades'
|
__tablename__ = 'trades'
|
||||||
|
|
||||||
id = Column(Integer, primary_key=True)
|
id = Column(Integer, primary_key=True)
|
||||||
|
|
||||||
|
orders = relationship("Order", order_by="Order.id")
|
||||||
|
|
||||||
exchange = Column(String, nullable=False)
|
exchange = Column(String, nullable=False)
|
||||||
pair = Column(String, nullable=False, index=True)
|
pair = Column(String, nullable=False, index=True)
|
||||||
is_open = Column(Boolean, nullable=False, default=True, index=True)
|
is_open = Column(Boolean, nullable=False, default=True, index=True)
|
||||||
|
Loading…
Reference in New Issue
Block a user