freqtrade_origin/freqtrade/persistence/pairlock.py

81 lines
3.0 KiB
Python
Raw Normal View History

from datetime import datetime, timezone
from typing import Any, ClassVar
2023-03-15 20:19:36 +00:00
from sqlalchemy import ScalarResult, String, or_, select
2023-03-16 17:07:22 +00:00
from sqlalchemy.orm import Mapped, mapped_column
from freqtrade.constants import DATETIME_PRINT_FORMAT
2023-02-28 06:03:22 +00:00
from freqtrade.persistence.base import ModelBase, SessionType
2023-02-16 07:04:45 +00:00
class PairLock(ModelBase):
"""
Pair Locks database model.
"""
2024-05-12 14:48:11 +00:00
__tablename__ = "pairlocks"
2023-03-15 20:12:06 +00:00
session: ClassVar[SessionType]
2023-02-16 07:14:07 +00:00
id: Mapped[int] = mapped_column(primary_key=True)
2023-02-16 07:14:07 +00:00
pair: Mapped[str] = mapped_column(String(25), nullable=False, index=True)
# lock direction - long, short or * (for both)
2023-02-16 07:14:07 +00:00
side: Mapped[str] = mapped_column(String(25), nullable=False, default="*")
reason: Mapped[str | None] = mapped_column(String(255), nullable=True)
# Time the pair was locked (start time)
2023-02-16 07:14:07 +00:00
lock_time: Mapped[datetime] = mapped_column(nullable=False)
# Time until the pair is locked (end time)
2023-02-16 07:14:07 +00:00
lock_end_time: Mapped[datetime] = mapped_column(nullable=False, index=True)
2023-02-16 07:14:07 +00:00
active: Mapped[bool] = mapped_column(nullable=False, default=True, index=True)
2023-02-16 07:14:07 +00:00
def __repr__(self) -> str:
lock_time = self.lock_time.strftime(DATETIME_PRINT_FORMAT)
lock_end_time = self.lock_end_time.strftime(DATETIME_PRINT_FORMAT)
return (
2024-05-12 14:48:11 +00:00
f"PairLock(id={self.id}, pair={self.pair}, side={self.side}, lock_time={lock_time}, "
f"lock_end_time={lock_end_time}, reason={self.reason}, active={self.active})"
)
@staticmethod
2023-03-16 05:44:53 +00:00
def query_pair_locks(
pair: str | None, now: datetime, side: str = "*"
2024-05-12 14:48:11 +00:00
) -> ScalarResult["PairLock"]:
"""
Get all currently active locks for this pair
:param pair: Pair to check for. Returns all current locks if pair is empty
:param now: Datetime object (generated via datetime.now(timezone.utc)).
"""
2024-05-12 14:48:11 +00:00
filters = [
PairLock.lock_end_time > now,
# Only active locks
PairLock.active.is_(True),
]
if pair:
filters.append(PairLock.pair == pair)
2024-05-12 14:48:11 +00:00
if side != "*":
filters.append(or_(PairLock.side == side, PairLock.side == "*"))
else:
2024-05-12 14:48:11 +00:00
filters.append(PairLock.side == "*")
2023-03-15 20:19:36 +00:00
return PairLock.session.scalars(select(PairLock).filter(*filters))
2023-03-16 05:48:12 +00:00
@staticmethod
2024-05-12 14:48:11 +00:00
def get_all_locks() -> ScalarResult["PairLock"]:
2023-03-16 05:48:12 +00:00
return PairLock.session.scalars(select(PairLock))
def to_json(self) -> dict[str, Any]:
return {
2024-05-12 14:48:11 +00:00
"id": self.id,
"pair": self.pair,
"lock_time": self.lock_time.strftime(DATETIME_PRINT_FORMAT),
"lock_timestamp": int(self.lock_time.replace(tzinfo=timezone.utc).timestamp() * 1000),
"lock_end_time": self.lock_end_time.strftime(DATETIME_PRINT_FORMAT),
"lock_end_timestamp": int(
self.lock_end_time.replace(tzinfo=timezone.utc).timestamp() * 1000
),
"reason": self.reason,
"side": self.side,
"active": self.active,
}