first version
This commit is contained in:
@@ -0,0 +1,311 @@
|
||||
package domain
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
)
|
||||
|
||||
type Mode string
|
||||
|
||||
const (
|
||||
ModeBacktest Mode = "backtest"
|
||||
ModePaper Mode = "paper"
|
||||
ModeSandbox Mode = "sandbox"
|
||||
ModeLiveReadonly Mode = "live_readonly"
|
||||
ModeLiveTrade Mode = "live_trade"
|
||||
)
|
||||
|
||||
func ParseMode(raw string) (Mode, error) {
|
||||
mode := Mode(strings.TrimSpace(raw))
|
||||
switch mode {
|
||||
case ModeBacktest, ModePaper, ModeSandbox, ModeLiveReadonly, ModeLiveTrade:
|
||||
return mode, nil
|
||||
default:
|
||||
return "", fmt.Errorf("unsupported app mode %q", raw)
|
||||
}
|
||||
}
|
||||
|
||||
func (m Mode) AllowsBrokerOrders() bool {
|
||||
return m == ModeSandbox || m == ModeLiveTrade
|
||||
}
|
||||
|
||||
func (m *Mode) UnmarshalText(text []byte) error {
|
||||
mode, err := ParseMode(string(text))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*m = mode
|
||||
return nil
|
||||
}
|
||||
|
||||
type Side string
|
||||
|
||||
const (
|
||||
SideBuy Side = "BUY"
|
||||
SideSell Side = "SELL"
|
||||
)
|
||||
|
||||
type OrderType string
|
||||
|
||||
const (
|
||||
OrderTypeLimit OrderType = "LIMIT"
|
||||
)
|
||||
|
||||
type OrderStatus string
|
||||
|
||||
const (
|
||||
OrderStatusNew OrderStatus = "NEW"
|
||||
OrderStatusSent OrderStatus = "SENT"
|
||||
OrderStatusPartiallyFilled OrderStatus = "PARTIALLY_FILLED"
|
||||
OrderStatusFilled OrderStatus = "FILLED"
|
||||
OrderStatusCancelled OrderStatus = "CANCELLED"
|
||||
OrderStatusRejected OrderStatus = "REJECTED"
|
||||
OrderStatusExpired OrderStatus = "EXPIRED"
|
||||
OrderStatusFailed OrderStatus = "FAILED"
|
||||
)
|
||||
|
||||
type SignalDecision string
|
||||
|
||||
const (
|
||||
DecisionEnter SignalDecision = "ENTER"
|
||||
DecisionSkip SignalDecision = "SKIP"
|
||||
DecisionReject SignalDecision = "REJECT"
|
||||
)
|
||||
|
||||
type PositionStatus string
|
||||
|
||||
const (
|
||||
PositionNoPosition PositionStatus = "NO_POSITION"
|
||||
PositionEntrySignalled PositionStatus = "ENTRY_SIGNALLED"
|
||||
PositionEntryOrderSent PositionStatus = "ENTRY_ORDER_SENT"
|
||||
PositionEntryPartiallyFilled PositionStatus = "ENTRY_PARTIALLY_FILLED"
|
||||
PositionEntryFilled PositionStatus = "ENTRY_FILLED"
|
||||
PositionHoldingOvernight PositionStatus = "HOLDING_OVERNIGHT"
|
||||
PositionExitOrderSent PositionStatus = "EXIT_ORDER_SENT"
|
||||
PositionExitPartiallyFilled PositionStatus = "EXIT_PARTIALLY_FILLED"
|
||||
PositionExitFilled PositionStatus = "EXIT_FILLED"
|
||||
PositionExitFailed PositionStatus = "EXIT_FAILED"
|
||||
PositionQuarantine PositionStatus = "QUARANTINE"
|
||||
)
|
||||
|
||||
type SystemState string
|
||||
|
||||
const (
|
||||
StateInit SystemState = "INIT"
|
||||
StateSyncInstruments SystemState = "SYNC_INSTRUMENTS"
|
||||
StateSyncMarketData SystemState = "SYNC_MARKET_DATA"
|
||||
StateGenerateSignals SystemState = "GENERATE_SIGNALS"
|
||||
StateWaitEntryWindow SystemState = "WAIT_ENTRY_WINDOW"
|
||||
StatePlaceEntryOrders SystemState = "PLACE_ENTRY_ORDERS"
|
||||
StateMonitorEntryOrders SystemState = "MONITOR_ENTRY_ORDERS"
|
||||
StateHoldOvernight SystemState = "HOLD_OVERNIGHT"
|
||||
StateWaitExitWindow SystemState = "WAIT_EXIT_WINDOW"
|
||||
StatePlaceExitOrders SystemState = "PLACE_EXIT_ORDERS"
|
||||
StateMonitorExitOrders SystemState = "MONITOR_EXIT_ORDERS"
|
||||
StateReconcile SystemState = "RECONCILE"
|
||||
StateReport SystemState = "REPORT"
|
||||
StateSleep SystemState = "SLEEP"
|
||||
StateHalted SystemState = "HALTED"
|
||||
)
|
||||
|
||||
type Severity string
|
||||
|
||||
const (
|
||||
SeverityInfo Severity = "INFO"
|
||||
SeverityWarn Severity = "WARN"
|
||||
SeverityAlert Severity = "ALERT"
|
||||
SeverityCritical Severity = "CRITICAL"
|
||||
)
|
||||
|
||||
type TradingStatus string
|
||||
|
||||
const (
|
||||
TradingStatusNormal TradingStatus = "NORMAL_TRADING"
|
||||
TradingStatusClosed TradingStatus = "CLOSED"
|
||||
TradingStatusUnknown TradingStatus = "UNKNOWN"
|
||||
)
|
||||
|
||||
type Instrument struct {
|
||||
InstrumentUID string
|
||||
Figi string
|
||||
Ticker string
|
||||
ClassCode string
|
||||
Name string
|
||||
Lot int64
|
||||
MinPriceIncrement decimal.Decimal
|
||||
Currency string
|
||||
Enabled bool
|
||||
FundType string
|
||||
ExpectedCommissionBpsPerSide decimal.Decimal
|
||||
FreeOrderLimitPerDay int
|
||||
Quarantine bool
|
||||
QuarantineReason string
|
||||
ExcludeReason string
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
func (i Instrument) MetadataValid() bool {
|
||||
return i.InstrumentUID != "" &&
|
||||
!strings.HasPrefix(i.InstrumentUID, "PENDING:") &&
|
||||
i.Lot > 0 &&
|
||||
i.MinPriceIncrement.IsPositive() &&
|
||||
strings.EqualFold(i.Currency, "RUB")
|
||||
}
|
||||
|
||||
type Candle struct {
|
||||
InstrumentUID string
|
||||
TradeDate time.Time
|
||||
Open decimal.Decimal
|
||||
High decimal.Decimal
|
||||
Low decimal.Decimal
|
||||
Close decimal.Decimal
|
||||
VolumeLots decimal.Decimal
|
||||
Source string
|
||||
LoadedAt time.Time
|
||||
}
|
||||
|
||||
type FeatureSet struct {
|
||||
InstrumentUID string
|
||||
TradeDate time.Time
|
||||
ROn decimal.Decimal
|
||||
RDay decimal.Decimal
|
||||
MuOn60 decimal.Decimal
|
||||
MuOn252 decimal.Decimal
|
||||
SigmaOn60 decimal.Decimal
|
||||
TStatOn60 decimal.Decimal
|
||||
WinOn60 decimal.Decimal
|
||||
EWMAOn decimal.Decimal
|
||||
SpreadBps decimal.Decimal
|
||||
HalfSpreadBps decimal.Decimal
|
||||
TickBps decimal.Decimal
|
||||
ADV20 decimal.Decimal
|
||||
ExpectedCostBps decimal.Decimal
|
||||
NetEdgeBps decimal.Decimal
|
||||
EntryIntervalVolume decimal.Decimal
|
||||
ExitIntervalVolume decimal.Decimal
|
||||
CalculatedAt time.Time
|
||||
}
|
||||
|
||||
type Signal struct {
|
||||
ID int64
|
||||
TradeDate time.Time
|
||||
InstrumentUID string
|
||||
Decision SignalDecision
|
||||
Score decimal.Decimal
|
||||
NetEdgeBps decimal.Decimal
|
||||
TargetNotional decimal.Decimal
|
||||
TargetLots int64
|
||||
RejectReason string
|
||||
ContextJSON string
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
type Order struct {
|
||||
ClientOrderID string
|
||||
BrokerOrderID string
|
||||
AccountIDHash string
|
||||
InstrumentUID string
|
||||
TradeDate time.Time
|
||||
Side Side
|
||||
OrderType OrderType
|
||||
LimitPrice decimal.Decimal
|
||||
QuantityLots int64
|
||||
FilledLots int64
|
||||
AvgFillPrice decimal.Decimal
|
||||
Status OrderStatus
|
||||
Commission decimal.Decimal
|
||||
AttemptNo int
|
||||
RawStateJSON string
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
type Position struct {
|
||||
ID int64
|
||||
AccountIDHash string
|
||||
InstrumentUID string
|
||||
OpenTradeDate time.Time
|
||||
Lots int64
|
||||
Lot int64
|
||||
ExitFilledLots int64
|
||||
AvgBuyPrice decimal.Decimal
|
||||
AvgSellPrice decimal.Decimal
|
||||
Status PositionStatus
|
||||
GrossPnL decimal.Decimal
|
||||
NetPnL decimal.Decimal
|
||||
CommissionTotal decimal.Decimal
|
||||
RealizedEdgeBps decimal.Decimal
|
||||
OpenedAt *time.Time
|
||||
ClosedAt *time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
type RiskEvent struct {
|
||||
ID int64
|
||||
TS time.Time
|
||||
Severity Severity
|
||||
EventType string
|
||||
InstrumentUID string
|
||||
Message string
|
||||
ContextJSON string
|
||||
}
|
||||
|
||||
type Holding struct {
|
||||
InstrumentUID string
|
||||
QuantityLots int64
|
||||
AveragePrice decimal.Decimal
|
||||
MarketValue decimal.Decimal
|
||||
}
|
||||
|
||||
type Portfolio struct {
|
||||
Equity decimal.Decimal
|
||||
Cash decimal.Decimal
|
||||
Holdings []Holding
|
||||
CheckedAt time.Time
|
||||
}
|
||||
|
||||
type OrderBookLevel struct {
|
||||
Price decimal.Decimal
|
||||
QuantityLots int64
|
||||
}
|
||||
|
||||
type OrderBook struct {
|
||||
InstrumentUID string
|
||||
Bids []OrderBookLevel
|
||||
Asks []OrderBookLevel
|
||||
Time time.Time
|
||||
ReceivedAt time.Time
|
||||
}
|
||||
|
||||
func (o OrderBook) BestBid() (decimal.Decimal, bool) {
|
||||
if len(o.Bids) == 0 {
|
||||
return decimal.Zero, false
|
||||
}
|
||||
return o.Bids[0].Price, true
|
||||
}
|
||||
|
||||
func (o OrderBook) BestAsk() (decimal.Decimal, bool) {
|
||||
if len(o.Asks) == 0 {
|
||||
return decimal.Zero, false
|
||||
}
|
||||
return o.Asks[0].Price, true
|
||||
}
|
||||
|
||||
type Operation struct {
|
||||
ID string
|
||||
InstrumentUID string
|
||||
Type string
|
||||
Payment decimal.Decimal
|
||||
Commission decimal.Decimal
|
||||
ExecutedAt time.Time
|
||||
}
|
||||
|
||||
type ReconciliationDiff struct {
|
||||
Kind string
|
||||
InstrumentUID string
|
||||
Message string
|
||||
Critical bool
|
||||
}
|
||||
Reference in New Issue
Block a user