feat(PORTFOLIO-003): add premium and spread for physical gold positions
This commit is contained in:
@@ -21,6 +21,8 @@ class Position:
|
||||
entry_price: Price per unit at purchase (in USD)
|
||||
entry_date: Date of position entry (for historical conversion lookups)
|
||||
entry_basis_mode: Entry basis mode ("weight" or "value_price")
|
||||
purchase_premium: Dealer markup over spot as percentage (e.g., Decimal("0.04") for 4%)
|
||||
bid_ask_spread: Expected sale discount below spot as percentage (e.g., Decimal("0.03") for 3%)
|
||||
notes: Optional notes about this position
|
||||
storage_cost_basis: Annual storage cost as percentage (e.g., Decimal("0.12") for 0.12%) or fixed amount
|
||||
storage_cost_period: Period for storage cost ("annual" or "monthly")
|
||||
@@ -35,6 +37,8 @@ class Position:
|
||||
entry_price: Decimal
|
||||
entry_date: date
|
||||
entry_basis_mode: str = "weight"
|
||||
purchase_premium: Decimal | None = None
|
||||
bid_ask_spread: Decimal | None = None
|
||||
notes: str = ""
|
||||
storage_cost_basis: Decimal | None = None
|
||||
storage_cost_period: str | None = None
|
||||
@@ -72,6 +76,8 @@ class Position:
|
||||
"entry_price": str(self.entry_price),
|
||||
"entry_date": self.entry_date.isoformat(),
|
||||
"entry_basis_mode": self.entry_basis_mode,
|
||||
"purchase_premium": str(self.purchase_premium) if self.purchase_premium is not None else None,
|
||||
"bid_ask_spread": str(self.bid_ask_spread) if self.bid_ask_spread is not None else None,
|
||||
"notes": self.notes,
|
||||
"storage_cost_basis": str(self.storage_cost_basis) if self.storage_cost_basis is not None else None,
|
||||
"storage_cost_period": self.storage_cost_period,
|
||||
@@ -90,6 +96,8 @@ class Position:
|
||||
entry_price=Decimal(data["entry_price"]),
|
||||
entry_date=date.fromisoformat(data["entry_date"]),
|
||||
entry_basis_mode=data.get("entry_basis_mode", "weight"),
|
||||
purchase_premium=(Decimal(data["purchase_premium"]) if data.get("purchase_premium") is not None else None),
|
||||
bid_ask_spread=(Decimal(data["bid_ask_spread"]) if data.get("bid_ask_spread") is not None else None),
|
||||
notes=data.get("notes", ""),
|
||||
storage_cost_basis=(
|
||||
Decimal(data["storage_cost_basis"]) if data.get("storage_cost_basis") is not None else None
|
||||
@@ -107,6 +115,8 @@ def create_position(
|
||||
entry_price: Decimal | None = None,
|
||||
entry_date: date | None = None,
|
||||
entry_basis_mode: str = "weight",
|
||||
purchase_premium: Decimal | None = None,
|
||||
bid_ask_spread: Decimal | None = None,
|
||||
notes: str = "",
|
||||
storage_cost_basis: Decimal | None = None,
|
||||
storage_cost_period: str | None = None,
|
||||
@@ -121,6 +131,8 @@ def create_position(
|
||||
entry_price: Entry price per unit (default: Decimal("2150"))
|
||||
entry_date: Entry date (default: today)
|
||||
entry_basis_mode: Entry basis mode (default: "weight")
|
||||
purchase_premium: Dealer markup over spot as percentage (default: None)
|
||||
bid_ask_spread: Expected sale discount below spot as percentage (default: None)
|
||||
notes: Optional notes
|
||||
storage_cost_basis: Annual storage cost as percentage or fixed amount (default: None)
|
||||
storage_cost_period: Period for storage cost ("annual" or "monthly", default: None)
|
||||
@@ -134,6 +146,8 @@ def create_position(
|
||||
entry_price=entry_price if entry_price is not None else Decimal("2150"),
|
||||
entry_date=entry_date or date.today(),
|
||||
entry_basis_mode=entry_basis_mode,
|
||||
purchase_premium=purchase_premium,
|
||||
bid_ask_spread=bid_ask_spread,
|
||||
notes=notes,
|
||||
storage_cost_basis=storage_cost_basis,
|
||||
storage_cost_period=storage_cost_period,
|
||||
|
||||
Reference in New Issue
Block a user