public IList <double> Execute(ISecurity sec) { //Context.Log(String.Format("[Heartbeat.Execute ( ID:{0} )] I'm checking timer settings.", m_id), MessageType.Warning, false); // PROD-5496 - В режиме оптимизации отключаюсь if (Context.IsOptimization) { return(Constants.EmptyListDouble); } var secrt = sec as ISecurityRt; if (secrt?.IsPortfolioActive != true) { return(Constants.EmptyListDouble); } TimerInfo timerState; string cashKey = VariableId + "_timerState"; { object localObj = Context.LoadObject(cashKey); timerState = localObj as TimerInfo; // PROD-3970 - 'Важный' объект if (timerState == null) { if (localObj is NotClearableContainer container && container.Content != null) { timerState = container.Content as TimerInfo; } } } if (timerState == null) { string msg = $"[RecalcScheduler({m_id})] Preparing new timer for agent '{Context.Runtime.TradeName}'..."; Context.Log(msg); timerState = TimerInfo.Create(Context, secrt, RecalcTime); var container = new NotClearableContainer(timerState); Context.StoreObject(cashKey, container); } else if (timerState.Timer == null) { // PROD-5427 - Добавляю счетчик этого аварийного события и логгирую int problemCounter = 0; if (s_problemCounters.ContainsKey(Context.Runtime.TradeName)) { problemCounter = s_problemCounters[Context.Runtime.TradeName]; } s_problemCounters[Context.Runtime.TradeName] = Interlocked.Increment(ref problemCounter); string msg = $"[RecalcScheduler({m_id})] Timer is null in agent '{Context.Runtime.TradeName}'. Problem counter: {problemCounter}"; Context.Log(msg, MessageType.Warning); if (problemCounter > 3) { // Если проблема систематически повторяется -- выбрасываю ассерт для дальнейшего анализа ситуации Contract.Assert(timerState.Timer != null, msg); } } else { // Если при изменении скрипта пересоздается агент, то контекст становится невалидным? if (!ReferenceEquals(Context, timerState.CallContext)) { // Если по какой-то причине изменился контекст, то создаём новый таймер... string msg = $"[RecalcScheduler({m_id})] Replacing timer for agent '{Context.Runtime.TradeName}'..."; Context.Log(msg, MessageType.Warning); // Создаём новый таймер. При этом используем НОВЫЙ m_id timerState = TimerInfo.Create(Context, secrt, RecalcTime); var container = new NotClearableContainer(timerState); Context.StoreObject(cashKey, container); } } int len = Context.BarsCount; double[] res = Context.GetArray <double>(len); if (len > 0) { res[len - 1] = m_id; } return(res); }