Files
Predictalytics/src/Predictalytics.Domain/Entities/Trade.cs
T

120 lines
4.8 KiB
C#

using Predictalytics.Domain.Enums;
using System.ComponentModel.DataAnnotations.Schema;
namespace Predictalytics.Domain.Entities;
/// <summary>
/// Represents a single trade executed by a trader on a prediction market.
/// </summary>
public class Trade
{
public long Id { get; set; }
/// <summary>Foreign key to the trader who made this trade.</summary>
public int TraderId { get; set; }
/// <summary>Platform where the trade occurred.</summary>
public PlatformType Platform { get; set; }
/// <summary>
/// Platform-specific trade ID for deduplication.
/// Format: "{txHash}_{assetId}_{side}" (max ~143 chars for new trades).
/// Legacy trades may include wallet address as 2nd segment.
/// </summary>
public string PlatformTradeId { get; set; } = string.Empty;
/// <summary>
/// Platform-specific market identifier string (conditionId on Polymarket, address on Limitless).
/// Kept as VARCHAR(66) for cross-referencing during import and reconciliation.
/// After full linking, prefer DbMarketId.
/// </summary>
public string MarketId { get; set; } = string.Empty;
/// <summary>
/// Foreign key to the internal Markets table. Populated during import when the market is known.
/// Null for trades whose market has not yet been synced.
/// </summary>
public int? DbMarketId { get; set; }
/// <summary>
/// Platform-specific token/asset ID (clobTokenId on Polymarket). Links to MarketOutcome.TokenId.
/// Kept as VARCHAR(66) until MarketOutcomeId is resolved.
/// </summary>
public string AssetId { get; set; } = string.Empty;
/// <summary>Foreign key to the resolved MarketOutcome (nullable until resolved via market sync).</summary>
public int? MarketOutcomeId { get; set; }
/// <summary>The outcome the trader bet on (e.g. "Yes", "No").</summary>
public string Outcome { get; set; } = string.Empty;
/// <summary>Buy or Sell.</summary>
public TradeSide Side { get; set; }
/// <summary>Price per share at execution (0.00 to 1.00 on Polymarket).</summary>
public decimal Price { get; set; }
/// <summary>Number of shares/tokens traded.</summary>
public decimal Size { get; set; }
/// <summary>Total notional value in USD.</summary>
public decimal Amount { get; set; }
/// <summary>When the trade was executed on the platform.</summary>
public DateTime ExecutedAt { get; set; }
/// <summary>Transaction hash (for blockchain-based platforms).</summary>
public string? TransactionHash { get; set; }
/// <summary>USDC size of the trade (raw currency size traded).</summary>
[Column(TypeName = "decimal(18,6)")]
public decimal? UsdcSize { get; set; }
/// <summary>Outcome index traded.</summary>
public int? OutcomeIndex { get; set; }
// ── Context Enrichment (AI Strategy Detection) ───────────
/// <summary>Market price 1 minute before trade execution.</summary>
[Column(TypeName = "decimal(18,4)")]
public decimal? PreTradePrice1m { get; set; }
/// <summary>Market price 1 minute after trade execution.</summary>
[Column(TypeName = "decimal(18,4)")]
public decimal? PostTradePrice1m { get; set; }
/// <summary>Indicates if high-res price context was fetched.</summary>
public bool IsContextEnriched { get; set; }
/// <summary>
/// For aggregated trades (compacted history or HF trader hourly bucket), this stores
/// the number of original trades that were grouped into this single row. Null means 1.
/// </summary>
public int? AggregatedCount { get; set; }
// ── Transient (not persisted) ──────────────────────────────────────────
/// <summary>
/// Wallet address of the trader, set by the provider during data ingestion.
/// NOT stored in the database — used transiently for trader discovery in MarketHistoryWorker.
/// </summary>
[NotMapped]
public string? TransientWallet { get; set; }
/// <summary>
/// Transient reference to the trader's display name from the platform, used to opportunistically
/// update the local name if it's currently a placeholder or empty.
/// </summary>
[NotMapped]
public string? TransientDisplayName { get; set; }
// ── Navigation ────────────────────────────────────────────────────────
public Trader Trader { get; set; } = null!;
public MarketOutcome? MarketOutcome { get; set; }
/// <summary>Analytics context containing high-resolution price data and slippage (if collected).</summary>
public TradeContext? Context { get; set; }
public Market? DbMarket { get; set; }
}