fix(scheduler): derive trading calendar from candles
Deploy / Test, build and deploy (push) Failing after 5m23s
Deploy / Test, build and deploy (push) Failing after 5m23s
This commit is contained in:
@@ -64,7 +64,7 @@ Common formats:
|
||||
| `TINVEST_RETRY_COUNT` | `3` | Number of T-Invest SDK attempts. |
|
||||
| `TINVEST_RETRY_BACKOFF_SEC` | `2` | Initial exponential backoff in seconds. |
|
||||
| `TINVEST_USE_SANDBOX` | `false` | Compatibility guard; valid only with `APP_MODE=sandbox`. |
|
||||
| `TINVEST_TRADING_CALENDAR_EXCHANGE` | `MOEX` | Exchange calendar used to load trading days. |
|
||||
| `TINVEST_TRADING_CALENDAR_EXCHANGE` | `MOEX` | Deprecated compatibility setting; historical feature calendars are derived from loaded daily candles. |
|
||||
|
||||
### DB
|
||||
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ APP_MODE=backtest go run ./cmd/bot
|
||||
| `TINVEST_RETRY_COUNT` | целое число попыток | `3` | `<= 0` трактуется как одна попытка | Общее число попыток для SDK-вызовов T-Invest через exponential backoff. Больше значение повышает устойчивость к кратким сбоям, но может дольше задерживать окончательную ошибку. |
|
||||
| `TINVEST_RETRY_BACKOFF_SEC` | целое число секунд | `2` | рекомендуется `>= 0` | Начальный интервал exponential backoff для SDK-вызовов T-Invest. Больше значение снижает частоту повторов при сбоях, но дольше задерживает окончательную ошибку. |
|
||||
| `TINVEST_USE_SANDBOX` | `true` или `false` | `false` | boolean; разрешено только при `APP_MODE=sandbox` | Защитный флаг совместимости. В `live_readonly` и `live_trade` запрещён валидацией, чтобы случайно не подменить фактическую среду исполнения. |
|
||||
| `TINVEST_TRADING_CALENDAR_EXCHANGE` | код биржевого календаря, например `MOEX` | `MOEX` | пустое значение заменяется на `MOEX` | Календарь торговых дней для загрузки истории и расчёта торгового цикла. |
|
||||
| `TINVEST_TRADING_CALENDAR_EXCHANGE` | устаревший код биржевого календаря, например `MOEX` | `MOEX` | пустое значение заменяется на `MOEX` | Оставлен для совместимости; исторический календарь признаков строится из загруженных дневных свечей. |
|
||||
|
||||
### DB
|
||||
|
||||
|
||||
@@ -251,9 +251,9 @@ func (s *Scheduler) prepareSignals(ctx context.Context, now time.Time) error {
|
||||
if err := s.svc.MarketData.BackfillDaily(ctx, instrumentsList, dailyFrom, tradeDate); err != nil {
|
||||
return err
|
||||
}
|
||||
tradingDays, err := s.svc.Gateway.GetTradingDays(ctx, s.cfg.TradingCalendarExchange, dailyFrom, tradeDate)
|
||||
tradingDays, err := s.tradingDaysFromDailyCandles(ctx, instrumentsList, dailyFrom, tradeDate.AddDate(0, 0, -1))
|
||||
if err != nil {
|
||||
return fmt.Errorf("load trading calendar %s: %w", s.cfg.TradingCalendarExchange, err)
|
||||
return err
|
||||
}
|
||||
s.svc.Features = s.svc.Features.WithTradingDays(tradingDays)
|
||||
minuteFrom := s.cfg.EntryWindowStart.On(tradeDate.AddDate(0, 0, -s.cfg.IntervalVolumeLookbackDays), s.cfg.Location)
|
||||
@@ -297,6 +297,33 @@ func (s *Scheduler) prepareSignals(ctx context.Context, now time.Time) error {
|
||||
return s.transitionTo(ctx, domain.StateWaitEntryWindow)
|
||||
}
|
||||
|
||||
func (s Scheduler) tradingDaysFromDailyCandles(ctx context.Context, instrumentsList []domain.Instrument, from, to time.Time) ([]time.Time, error) {
|
||||
if to.Before(from) {
|
||||
return nil, nil
|
||||
}
|
||||
seen := make(map[time.Time]struct{})
|
||||
for _, instrument := range instrumentsList {
|
||||
if !instrument.Enabled || instrument.Quarantine {
|
||||
continue
|
||||
}
|
||||
candles, err := s.svc.Repo.ListDailyCandles(ctx, instrument.InstrumentUID, from, to)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("load daily candles for trading calendar %s: %w", instrument.Ticker, err)
|
||||
}
|
||||
for _, candle := range candles {
|
||||
seen[tradingDate(candle.TradeDate)] = struct{}{}
|
||||
}
|
||||
}
|
||||
days := make([]time.Time, 0, len(seen))
|
||||
for day := range seen {
|
||||
days = append(days, day)
|
||||
}
|
||||
sort.Slice(days, func(i, j int) bool {
|
||||
return days[i].Before(days[j])
|
||||
})
|
||||
return days, nil
|
||||
}
|
||||
|
||||
func (s Scheduler) generateInstrumentSignal(ctx context.Context, tradeDate time.Time, openPositionCount int, instrument domain.Instrument) (signalCandidate, error) {
|
||||
book, err := s.svc.MarketData.LatestQuote(ctx, instrument.InstrumentUID, s.cfg.QuoteDepth, s.cfg.MaxQuoteAge)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user