Introduce Order database model
This commit is contained in:
parent
7d03a067ee
commit
171a52b21a
@ -487,6 +487,7 @@ class Exchange:
|
||||
'side': side,
|
||||
'remaining': _amount,
|
||||
'datetime': arrow.utcnow().isoformat(),
|
||||
'timestamp': arrow.utcnow().timestamp,
|
||||
'status': "closed" if ordertype == "market" else "open",
|
||||
'fee': None,
|
||||
'info': {}
|
||||
|
@ -22,7 +22,7 @@ from freqtrade.exceptions import (DependencyException, ExchangeError,
|
||||
from freqtrade.exchange import timeframe_to_minutes, timeframe_to_next_date
|
||||
from freqtrade.misc import safe_value_fallback, safe_value_fallback2
|
||||
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.rpc import RPCManager, RPCMessageType
|
||||
from freqtrade.state import State
|
||||
@ -527,6 +527,7 @@ class FreqtradeBot:
|
||||
order = self.exchange.buy(pair=pair, ordertype=order_type,
|
||||
amount=amount, rate=buy_limit_requested,
|
||||
time_in_force=time_in_force)
|
||||
order_obj = Order.parse_from_ccxt_object(order, pair)
|
||||
order_id = order['id']
|
||||
order_status = order.get('status', None)
|
||||
|
||||
@ -580,6 +581,7 @@ class FreqtradeBot:
|
||||
strategy=self.strategy.get_strategy_name(),
|
||||
timeframe=timeframe_to_minutes(self.config['timeframe'])
|
||||
)
|
||||
trade.orders.append(order_obj)
|
||||
|
||||
# Update fees if order is closed
|
||||
if order_status == 'closed':
|
||||
@ -781,6 +783,9 @@ class FreqtradeBot:
|
||||
stoploss_order = self.exchange.stoploss(pair=trade.pair, amount=trade.amount,
|
||||
stop_price=stop_price,
|
||||
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'])
|
||||
return True
|
||||
except InvalidOrderException as e:
|
||||
@ -1123,12 +1128,15 @@ class FreqtradeBot:
|
||||
return False
|
||||
|
||||
# Execute sell and update trade record
|
||||
order = self.exchange.sell(pair=str(trade.pair),
|
||||
order = self.exchange.sell(pair=trade.pair,
|
||||
ordertype=order_type,
|
||||
amount=amount, rate=limit,
|
||||
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.close_rate_requested = limit
|
||||
trade.sell_reason = sell_reason.value
|
||||
|
@ -1,3 +1,4 @@
|
||||
# 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
|
||||
|
||||
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)
|
||||
from sqlalchemy.exc import NoSuchModuleError
|
||||
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.session import sessionmaker
|
||||
from sqlalchemy.pool import StaticPool
|
||||
@ -85,13 +85,71 @@ def clean_dry_run_db() -> 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 used to define a trade structure
|
||||
Trade database model.
|
||||
Also handles updating and querying trades
|
||||
"""
|
||||
__tablename__ = 'trades'
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
|
||||
orders = relationship("Order", order_by="Order.id")
|
||||
|
||||
exchange = Column(String, nullable=False)
|
||||
pair = Column(String, nullable=False, index=True)
|
||||
is_open = Column(Boolean, nullable=False, default=True, index=True)
|
||||
|
Loading…
Reference in New Issue
Block a user