Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 0 additions & 84 deletions bots/controllers/directional_trading/ai_livestream.py

This file was deleted.

2 changes: 2 additions & 0 deletions bots/controllers/directional_trading/dman_v3.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class DManV3ControllerConfig(DirectionalTradingControllerConfigBase):
)
dca_spreads: List[Decimal] = Field(
default="0.001,0.018,0.15,0.25",
validate_default=True,
json_schema_extra={
"prompt": "Enter the spreads for each DCA level (comma-separated) if dynamic_spread=True this value "
"will multiply the Bollinger Bands width, e.g. if the Bollinger Bands width is 0.1 (10%)"
Expand All @@ -56,6 +57,7 @@ class DManV3ControllerConfig(DirectionalTradingControllerConfigBase):
)
dca_amounts_pct: List[Decimal] = Field(
default=None,
validate_default=True,
json_schema_extra={
"prompt": "Enter the amounts for each DCA level (as a percentage of the total balance, "
"comma-separated). Don't worry about the final sum, it will be normalized. ",
Expand Down
16 changes: 12 additions & 4 deletions bots/controllers/generic/pmm.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,27 +65,31 @@ class PMMConfig(ControllerConfigBase):
)
buy_spreads: List[float] = Field(
default="0.01,0.02",
validate_default=True,
json_schema_extra={
"prompt_on_new": True, "is_updatable": True,
"prompt": "Enter a comma-separated list of buy spreads (e.g., '0.01, 0.02'):",
}
)
sell_spreads: List[float] = Field(
default="0.01,0.02",
validate_default=True,
json_schema_extra={
"prompt_on_new": True, "is_updatable": True,
"prompt": "Enter a comma-separated list of sell spreads (e.g., '0.01, 0.02'):",
}
)
buy_amounts_pct: Union[List[Decimal], None] = Field(
default=None,
validate_default=True,
json_schema_extra={
"prompt_on_new": True, "is_updatable": True,
"prompt": "Enter a comma-separated list of buy amounts as percentages (e.g., '50, 50'), or leave blank to distribute equally:",
}
)
sell_amounts_pct: Union[List[Decimal], None] = Field(
default=None,
validate_default=True,
json_schema_extra={
"prompt_on_new": True, "is_updatable": True,
"prompt": "Enter a comma-separated list of sell amounts as percentages (e.g., '50, 50'), or leave blank to distribute equally:",
Expand Down Expand Up @@ -180,13 +184,17 @@ def parse_and_validate_amounts(cls, v, validation_info: ValidationInfo):
field_name = validation_info.field_name
if v is None or v == "":
spread_field = field_name.replace('amounts_pct', 'spreads')
return [1 for _ in validation_info.data[spread_field]]
return [Decimal("1") for _ in validation_info.data[spread_field]]
if isinstance(v, str):
return [float(x.strip()) for x in v.split(',')]
elif isinstance(v, list) and len(v) != len(validation_info.data[field_name.replace('amounts_pct', 'spreads')]):
parsed = [Decimal(x.strip()) for x in v.split(',')]
elif isinstance(v, list):
parsed = [Decimal(str(x)) for x in v]
else:
parsed = [Decimal(str(v))]
if len(parsed) != len(validation_info.data[field_name.replace('amounts_pct', 'spreads')]):
raise ValueError(
f"The number of {field_name} must match the number of {field_name.replace('amounts_pct', 'spreads')}.")
return v
return parsed

@field_validator('position_mode', mode="before")
@classmethod
Expand Down
16 changes: 12 additions & 4 deletions bots/controllers/generic/pmm_adjusted.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,27 +69,31 @@ class PMMAdjustedConfig(ControllerConfigBase):
)
buy_spreads: List[float] = Field(
default="0.01,0.02",
validate_default=True,
json_schema_extra={
"prompt_on_new": True, "is_updatable": True,
"prompt": "Enter a comma-separated list of buy spreads (e.g., '0.01, 0.02'):",
}
)
sell_spreads: List[float] = Field(
default="0.01,0.02",
validate_default=True,
json_schema_extra={
"prompt_on_new": True, "is_updatable": True,
"prompt": "Enter a comma-separated list of sell spreads (e.g., '0.01, 0.02'):",
}
)
buy_amounts_pct: Union[List[Decimal], None] = Field(
default=None,
validate_default=True,
json_schema_extra={
"prompt_on_new": True, "is_updatable": True,
"prompt": "Enter a comma-separated list of buy amounts as percentages (e.g., '50, 50'), or leave blank to distribute equally:",
}
)
sell_amounts_pct: Union[List[Decimal], None] = Field(
default=None,
validate_default=True,
json_schema_extra={
"prompt_on_new": True, "is_updatable": True,
"prompt": "Enter a comma-separated list of sell amounts as percentages (e.g., '50, 50'), or leave blank to distribute equally:",
Expand Down Expand Up @@ -184,13 +188,17 @@ def parse_and_validate_amounts(cls, v, validation_info: ValidationInfo):
field_name = validation_info.field_name
if v is None or v == "":
spread_field = field_name.replace('amounts_pct', 'spreads')
return [1 for _ in validation_info.data[spread_field]]
return [Decimal("1") for _ in validation_info.data[spread_field]]
if isinstance(v, str):
return [float(x.strip()) for x in v.split(',')]
elif isinstance(v, list) and len(v) != len(validation_info.data[field_name.replace('amounts_pct', 'spreads')]):
parsed = [Decimal(x.strip()) for x in v.split(',')]
elif isinstance(v, list):
parsed = [Decimal(str(x)) for x in v]
else:
parsed = [Decimal(str(v))]
if len(parsed) != len(validation_info.data[field_name.replace('amounts_pct', 'spreads')]):
raise ValueError(
f"The number of {field_name} must match the number of {field_name.replace('amounts_pct', 'spreads')}.")
return v
return parsed

@field_validator('position_mode', mode="before")
@classmethod
Expand Down
13 changes: 7 additions & 6 deletions bots/controllers/generic/pmm_mister.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ class PMMisterConfig(ControllerConfigBase):
target_base_pct: Decimal = Field(default=Decimal("0.5"), json_schema_extra={"is_updatable": True})
min_base_pct: Decimal = Field(default=Decimal("0.3"), json_schema_extra={"is_updatable": True})
max_base_pct: Decimal = Field(default=Decimal("0.7"), json_schema_extra={"is_updatable": True})
buy_spreads: List[float] = Field(default="0.0005", json_schema_extra={"is_updatable": True})
sell_spreads: List[float] = Field(default="0.0005", json_schema_extra={"is_updatable": True})
buy_amounts_pct: Union[List[Decimal], None] = Field(default="1", json_schema_extra={"is_updatable": True})
sell_amounts_pct: Union[List[Decimal], None] = Field(default="1", json_schema_extra={"is_updatable": True})
buy_spreads: List[float] = Field(default="0.0005", validate_default=True, json_schema_extra={"is_updatable": True})
sell_spreads: List[float] = Field(default="0.0005", validate_default=True, json_schema_extra={"is_updatable": True})
buy_amounts_pct: Union[List[Decimal], None] = Field(default="1", validate_default=True, json_schema_extra={"is_updatable": True})
sell_amounts_pct: Union[List[Decimal], None] = Field(default="1", validate_default=True, json_schema_extra={"is_updatable": True})
executor_refresh_time: int = Field(default=30, json_schema_extra={"is_updatable": True})

# Enhanced timing parameters
Expand Down Expand Up @@ -89,9 +89,10 @@ def parse_and_validate_amounts(cls, v, validation_info: ValidationInfo):
field_name = validation_info.field_name
if v is None or v == "":
spread_field = field_name.replace('amounts_pct', 'spreads')
return [1 for _ in validation_info.data[spread_field]]
return [Decimal("1") for _ in validation_info.data[spread_field]]
parsed = parse_comma_separated_list(v)
if isinstance(parsed, list) and len(parsed) != len(
parsed = [Decimal(str(x)) for x in parsed]
if len(parsed) != len(
validation_info.data[field_name.replace('amounts_pct', 'spreads')]):
raise ValueError(
f"The number of {field_name} must match the number of {field_name.replace('amounts_pct', 'spreads')}.")
Expand Down
14 changes: 10 additions & 4 deletions bots/controllers/market_making/dman_maker_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ class DManMakerV2Config(MarketMakingControllerConfigBase):
# DCA configuration
dca_spreads: List[Decimal] = Field(
default="0.01,0.02,0.04,0.08",
validate_default=True,
json_schema_extra={"prompt": "Enter a comma-separated list of spreads for each DCA level: ", "prompt_on_new": True})
dca_amounts: List[Decimal] = Field(
default="0.1,0.2,0.4,0.8",
validate_default=True,
json_schema_extra={"prompt": "Enter a comma-separated list of amounts for each DCA level: ", "prompt_on_new": True})
top_executor_refresh_time: Optional[float] = Field(default=None, json_schema_extra={"is_updatable": True})
executor_activation_bounds: Optional[List[Decimal]] = Field(default=None, json_schema_extra={"is_updatable": True})
Expand Down Expand Up @@ -55,13 +57,17 @@ def parse_dca_spreads(cls, v):
@classmethod
def parse_and_validate_dca_amounts(cls, v, validation_info):
if v is None or v == "":
return [1 for _ in validation_info.data['dca_spreads']]
return [Decimal("1") for _ in validation_info.data['dca_spreads']]
if isinstance(v, str):
return [float(x.strip()) for x in v.split(',')]
elif isinstance(v, list) and len(v) != len(validation_info.data['dca_spreads']):
parsed = [Decimal(x.strip()) for x in v.split(',')]
elif isinstance(v, list):
parsed = [Decimal(str(x)) for x in v]
else:
parsed = [Decimal(str(v))]
if len(parsed) != len(validation_info.data['dca_spreads']):
raise ValueError(
f"The number of dca amounts must match the number of {validation_info.data['dca_spreads']}.")
return v
return parsed


class DManMakerV2(MarketMakingControllerBase):
Expand Down
5 changes: 5 additions & 0 deletions database/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ async def _run_migrations(self, conn):
"executors", "error_log",
"ALTER TABLE executors ADD COLUMN error_log TEXT"
),
# Add cum_fees_quote to position_holds table for tracking fees
(
"position_holds", "cum_fees_quote",
"ALTER TABLE position_holds ADD COLUMN cum_fees_quote NUMERIC(30,18) NOT NULL DEFAULT 0"
),
]
for table, column, sql in migrations:
try:
Expand Down
1 change: 1 addition & 0 deletions database/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,7 @@ class PositionHoldRecord(Base):
sell_amount_base = Column(Numeric(precision=30, scale=18), nullable=False, default=0)
sell_amount_quote = Column(Numeric(precision=30, scale=18), nullable=False, default=0)
realized_pnl_quote = Column(Numeric(precision=30, scale=18), nullable=False, default=0)
cum_fees_quote = Column(Numeric(precision=30, scale=18), nullable=False, default=0)

# Tracking
executor_ids = Column(Text, nullable=True) # JSON array of executor IDs
Expand Down
7 changes: 6 additions & 1 deletion database/repositories/executor_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,10 +195,13 @@ async def upsert_position_hold(
sell_amount_base: Decimal,
sell_amount_quote: Decimal,
realized_pnl_quote: Decimal,
executor_ids: List[str]
cum_fees_quote: Decimal = Decimal("0"),
executor_ids: List[str] = None
) -> PositionHoldRecord:
"""Create or update a position hold record."""
import json as _json
if executor_ids is None:
executor_ids = []

stmt = select(PositionHoldRecord).where(and_(
PositionHoldRecord.account_name == account_name,
Expand All @@ -216,6 +219,7 @@ async def upsert_position_hold(
record.sell_amount_base = sell_amount_base
record.sell_amount_quote = sell_amount_quote
record.realized_pnl_quote = realized_pnl_quote
record.cum_fees_quote = cum_fees_quote
record.executor_ids = _json.dumps(executor_ids)
else:
record = PositionHoldRecord(
Expand All @@ -228,6 +232,7 @@ async def upsert_position_hold(
sell_amount_base=sell_amount_base,
sell_amount_quote=sell_amount_quote,
realized_pnl_quote=realized_pnl_quote,
cum_fees_quote=cum_fees_quote,
executor_ids=_json.dumps(executor_ids),
status="ACTIVE",
)
Expand Down
Loading
Loading