
- Created Alembic migrations for SQLite database - Set up database initialization on app startup - Fixed linting issues with Ruff - Updated README with comprehensive documentation - Configured startup tasks and health checks
98 lines
3.6 KiB
Python
98 lines
3.6 KiB
Python
from datetime import datetime
|
|
from sqlalchemy import Boolean, Column, Float, Integer, String, DateTime, Text, ForeignKey
|
|
from sqlalchemy.orm import relationship
|
|
|
|
from app.db.base import Base
|
|
|
|
|
|
class ArbitrageOpportunity(Base):
|
|
__tablename__ = "arbitrage_opportunities"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
created_at = Column(DateTime, default=datetime.utcnow, index=True)
|
|
|
|
# Token information
|
|
token_address = Column(String, index=True)
|
|
token_symbol = Column(String, index=True)
|
|
|
|
# Price information
|
|
source_dex = Column(String, index=True)
|
|
target_dex = Column(String, index=True)
|
|
source_price = Column(Float)
|
|
target_price = Column(Float)
|
|
price_difference = Column(Float) # Absolute price difference
|
|
price_difference_percent = Column(Float, index=True) # Percentage difference
|
|
|
|
# Profit details
|
|
estimated_profit_usd = Column(Float)
|
|
estimated_profit_token = Column(Float)
|
|
|
|
# Trade parameters
|
|
max_trade_amount_usd = Column(Float)
|
|
max_trade_amount_token = Column(Float)
|
|
slippage_estimate = Column(Float)
|
|
fees_estimate = Column(Float)
|
|
|
|
# Status
|
|
is_viable = Column(Boolean, default=False, index=True) # Whether it meets profit threshold
|
|
was_executed = Column(Boolean, default=False, index=True) # Whether a trade was attempted
|
|
|
|
# Relationships
|
|
trades = relationship("Trade", back_populates="opportunity")
|
|
|
|
def __repr__(self):
|
|
return f"<ArbitrageOpportunity {self.token_symbol}: {self.source_dex}->{self.target_dex} {self.price_difference_percent:.2f}%>"
|
|
|
|
|
|
class Trade(Base):
|
|
__tablename__ = "trades"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
created_at = Column(DateTime, default=datetime.utcnow, index=True)
|
|
|
|
# Reference to opportunity
|
|
opportunity_id = Column(Integer, ForeignKey("arbitrage_opportunities.id"), index=True)
|
|
opportunity = relationship("ArbitrageOpportunity", back_populates="trades")
|
|
|
|
# Trade details
|
|
token_address = Column(String, index=True)
|
|
token_symbol = Column(String, index=True)
|
|
source_dex = Column(String)
|
|
target_dex = Column(String)
|
|
|
|
# Amounts
|
|
input_amount = Column(Float) # Amount in token
|
|
input_amount_usd = Column(Float) # USD value at execution time
|
|
output_amount = Column(Float) # Amount in token
|
|
output_amount_usd = Column(Float) # USD value at execution time
|
|
|
|
# Trade outcome
|
|
profit_amount = Column(Float) # Amount in token
|
|
profit_amount_usd = Column(Float) # USD value
|
|
profit_percent = Column(Float) # Percentage gain
|
|
|
|
# Transaction data
|
|
tx_signature = Column(String, unique=True, index=True, nullable=True) # Solana transaction signature
|
|
tx_status = Column(String, index=True) # success, failed, pending
|
|
tx_error = Column(Text, nullable=True) # Error message if failed
|
|
|
|
def __repr__(self):
|
|
return f"<Trade {self.id}: {self.token_symbol} {self.profit_percent:.2f}% {'SUCCESS' if self.tx_status == 'success' else self.tx_status.upper()}>"
|
|
|
|
|
|
class SystemEvent(Base):
|
|
__tablename__ = "system_events"
|
|
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
timestamp = Column(DateTime, default=datetime.utcnow, index=True)
|
|
|
|
# Event categorization
|
|
event_type = Column(String, index=True) # startup, shutdown, error, warning, info
|
|
component = Column(String, index=True) # which component generated the event
|
|
|
|
# Event details
|
|
message = Column(Text)
|
|
details = Column(Text, nullable=True)
|
|
|
|
def __repr__(self):
|
|
return f"<SystemEvent {self.event_type.upper()}: {self.component} - {self.message[:50]}>" |