← Back

проблемы с остановкой стратегии

где-то в программе пытаюсь остановить стратегию if (strat.ProcessState == StrategyProcessStates.Stopped) strat.Start(); else strat.Stop();

... в моей производной стратегии от Strategy ... protected override void OnStopping() { Trader.QuotesChanged -= _trader_QuotesChanged; }

после выхода из этого метода программа зависает(чаще чем не виснет) по непонятным для меня причинам. Если кто сталкивался подскажите в чем может быть проблема? спс

Comments (21)

Login or Create account, Log in or register to leave a comment

Tauler
Tauler

Вы просто в момент остановки стратегии (когда она Stopped) заново ее стартуете, а когда она Runned - останавливаетете. получается вечный цикл - старт - остановка-старт-остановка

Serg
Serg Author

Не совсем понимаю почему... ведь первая часть кода вызывается при нажатии кнопки и никак не должна зацикливаться... или я не прав?

Mikhail Sukhov
Mikhail Sukhov

А что за стратегия? Собственная или из примеров?

Serg
Serg Author

ÓÏÂÓÔ×ÅÎÎÁÑ. public class Arbitrage : Strategy { ... ÐÅÒÅÍÅÎÎÙÅ ... public Arbitrage(QuikTrader trader, TradeSec ts1, TradeSec ts2, double spreadInPercent, int minimalQty, int maxiQty) : base() { _trader = trader; this.Interval = TimeSpan.FromSeconds(1); minQty = minimalQty; maxQty = maxiQty; Portf1 = ts1.p; Portf2 = ts2.p; ClientCode1 = ts1.client; ClientCode2 = ts2.client; Sec1 = ts1.s; Sec2 = ts2.s; k1 = ts1.koef; k2 = ts2.koef; Spread = spreadInPercent; md1 = new MarketDepth(Sec1); md2 = new MarketDepth(Sec2); _trader.RegisterQuotes(Sec1); _trader.RegisterQuotes(Sec2); _trader.QuotesChanged += new Action<MarketDepth>(_trader_QuotesChanged); }

   void _trader_QuotesChanged(MarketDepth md)
    {
        if (md.Security == Sec1)
        {
            md1 = md;
        }
        if (md.Security == Sec2)
        {
            md2 = md;
        }
    }

   protected override bool OnProcess()
    {
        if (this.ProcessState == StrategyProcessStates.Stopping)
        {
            return false;
        }
        if (!this.buzzy)
        {
            this.buzzy = true;
            var ords = AlgoSpread();
            if (ords != null && ords.Length >= 2)
            {
                // done ËÌÉÒÉÎÇ?
                if (!Sec1.Exchange.IsTradeTime(Trader) || !

Sec2.Exchange.IsTradeTime(Trader)) { AddLog(ErrorState, "îÅÔÏÒÇÏ×ÒÅ ×ÒÅÍÑ", this); return true; }

               foreach (Order o in ords)
                {
                    if (o.Portfolio == Portf1)
                        _trader.ClientCode = ClientCode1 + "//" +

orderParNum.ToString(); else if (o.Portfolio == Portf2) _trader.ClientCode = ClientCode2 + "//" + orderParNum.ToString(); else _trader.ClientCode = "X";

                   AddLog(ErrorState, "new order " +

o.Direction.ToString() + " " + o.Security.Code + " " + o.Price + " " + o.Volume, this);

                   try
                    {
                        RegisterOrder(o);
                    }
                    catch (Exception regOrderError)
                    {
                        AddLog(this.ErrorState, " ïÛÉÂËÁ

×ÙÓÔÁ×ÌÅÎÉÑ ÚÁÑ×ËÉ", this); AddLog(ErrorState, regOrderError.Message, this); } } } this.buzzy = false; } return true; }

   protected override void OnRunned()
    {
        base.OnRunned();
        buzzy = false;
    }

   void QuotesChanged(OrderDirections arg1, IDictionary<int,

Quote> arg2) { if (!buzzy) this.OnProcess(); }

   protected override void OnStopping()
    {
        Trader.QuotesChanged -= _trader_QuotesChanged;
        base.OnStopping();
    }

×ÏÔ ÐÒÉÍÅÒÎÏ ÔÁË. ÓÔÁÒÁÌÓÑ ÄÅÌÁÔØ ËÁË × ÐÒÉÍÅÒÁÈ ÎÏ ×ÉÄÉÍÏ ÞÔÏÔÏ ÕÐÕÓÔÉÌ.

Serg
Serg Author

после выхода из OnStopping() сразу завис :(

Mikhail Sukhov
Mikhail Sukhov

А что значит завис? В чем это проявилось?

Serg
Serg Author

прога виснет. в логах вижу что стратегия останавливается но не вижу что она остановилась. еще раз повторюсь такая ситуация проявляется не регулярно но довольно часто.

Mikhail Sukhov
Mikhail Sukhov

Так прога виснет или стратегия не нотифицирует о своей остановке? Какая версия S#?

Serg
Serg Author

кажется разобрался. я видимо заумно (не правильно) использовал Strategy.Log вот как было:

private void ToLog(string message) { if (this.messageBox.InvokeRequired) { SetTextDeleg d = new SetTextDeleg(ToLog); this.Invoke(d, new object[] ); } else

messageBox.AppendText(DateTime.Now.ToString("HH:mm:ss.fff")+ ": " + message + "\r\n"); }

void Log(Strategy arg1, StrategyErrorStates arg2, string arg3) { ToLog(arg3); }

strat = new Arbitrage(quik, t1, t2, Convert.ToDouble(textBox1.Text), 1, 20); strat.Log += new Action<Strategy, StrategyErrorStates, string>(Log);

избавившись от strat.Log += ... все стало работать нормально. осталось понять где ошибка. думаю в методе ToLog...

Serg
Serg Author

Михаил, а в чем может быть причина того что во время выполнения стратегии метод ToLog работает нормально, а после OnStopping происходит зависание?

Mikhail Sukhov
Mikhail Sukhov

А как часто вызывается Log событие? Invoke - это ведь синхронизация с ГУИ потоком. Может быть фишка в том, что все время уходит на эту саму синхронизацию?

Serg
Serg Author

вызывается минимум раз в секунду, а то и чаще. пробую обновлять данные порциями - не очень информативно. видимо нужно придумать прокладку между гуи и логгированием. хотя по сути логи нужны лишь при тестировании.

Mikhail Sukhov
Mikhail Sukhov

А если писать в файл?

Serg
Serg Author

в файл пишу через StategyLogger все норм. но если часто писать то бывает что строки одна на другую вылазят) А как обстоят дела с wpf и LogWindow? там таких проблем нет?

Mikhail Sukhov
Mikhail Sukhov

Строки вылазят одна на другую - это как?

В LogWindow может быть чуть шустрее, за счет того, что он не конкатенирует текст в контроле, а используется ListView. Попробуйте, может и хватит скорости. А вообще вариант напрашивается писать в некую очередь, из которой ГУИ поток выгребает данные и отображает на форме.

Иванов Андрей
Иванов Андрей

Думаю, это когда несколько потоков параллельно пишут в один файл.

Mikhail Sukhov
Mikhail Sukhov

А что с ними произойдет? Будут разрыва в строчках? Или просто строчки будут идти одна за другой но из разных стратегий?

Иванов Андрей
Иванов Андрей

Строчки одна за другой, но из разных стратегий, будут идти при любом раскладе -- организовывать в многопоточной многопроцессорной среде ордеринг потоков данных обычно неразумно. Где-то рядом обсуждали про приход данных об изменении баланса для закрытой сделки или что-то типа того -- это из той же серии. Если я правильно понял про строки -- каждая строка это одна запись в лог.

Разрывы в строках да, могут быть. Может быть перемешано. Это в лучшем случае =) А в худшем можно получить мусор, потому что StreamWriter не тредсейфовый и можно поломать его состояние. Но такое получить непросто, надо высокую concurrency иметь, чтобы постоянно ловить.

Лечится просто. private object _syncRoot; // вместо этого можно использовать любой reference type филд

lock(_syncRoot) { _writer.WriteLine("{0:T} {1}", DateTime.Now, message);

Вряд ли синхронизация спасёт автора темы, но с логом всё будет нормально.

Mikhail Sukhov
Mikhail Sukhov

Да, почитал про StreamWriter. Не все так хорошо. Заодно наткнулся на интересный методhttp://msdn.microsoft.com/en-us/library/system.io.textwriter.synchronized.aspx

Думаю будет элегантнее, чем вводить в коде свой маркер.

Serg
Serg Author

Вот что иногда бывает в лог файле (первые 5 строк):

S S 12:33:36.0820929 working 0820929 S запущена. S запуS 12:33:36.0977180 working S 12:33:36.0977180 working S 12:33:36.1133431 working

а в OnProcess сделано так: protected override bool OnProcess() { if (this.ProcessState == StrategyProcessStates.Stopping) return false;

       int inUse = Interlocked.CompareExchange(ref _inUse, 1, 0);
        if (inUse == 0)
        {
            try
            {
                AddLog(StrategyErrorStates.Error, /

*DateTime.Now.ToString("H:mm:ss:fff") + */" working", this); AddLog(StrategyErrorStates.None, / *DateTime.Now.ToString("H:mm:ss:fff") + */" working", this); AddLog(StrategyErrorStates.Warning, / *DateTime.Now.ToString("H:mm:ss:fff") + */" working", this); } finally { Interlocked.Exchange(ref _inUse, 0); } } return true; } а интервал стратегии this.Interval = TimeSpan.Zero;

Serg
Serg Author

Свою проблему решил следующим образом: создал список в который добавляются данные из Strategy.Log. добавил таймер на форму и теперь по таймеру синхронизирую гуи и свой список с логом. пока вроде все работает)