﻿<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type='text/css' href='https://stocksharp.com/css/style.css'?>
<?xml-stylesheet type='text/css' href='https://stocksharp.com/css/bbeditor.css'?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title type="html">Пример событийной стратегии на свечках</title>
  <id>~/topic/1814/primer-sobytiinoi-strategii-na-svechkah/</id>
  <rights type="text">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  <updated>2026-06-14T22:56:18Z</updated>
  <logo>https://stocksharp.com/images/logo.png</logo>
  <link href="https://stocksharp.com/handlers/atom.ashx?category=topic&amp;id=1814" rel="self" type="application/rss+xml" />
  <entry>
    <id>https://stocksharp.com/posts/m/10309/</id>
    <title type="text">Пытаюсь разобраться в том, как работает событийная стратегия на свечках. Насколько я могу понять, со...</title>
    <published>2011-08-14T13:03:32Z</published>
    <updated>2012-02-02T09:04:27Z</updated>
    <author>
      <name>Church</name>
      <uri>https://stocksharp.com/users/459/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <content type="html">&lt;p&gt;Пытаюсь разобраться в том, как работает событийная стратегия на свечках. Насколько я могу понять, со времени выпуска документации механизмы изменились и описанные на форуме и в API .when.do конструкции на CandleToken'ах не работают, а без исходников понять почему - не получается.&lt;/p&gt;
&lt;p&gt;Просьба к участникам форума - выложите, пожалуйста, каркас такой стратегии - без логики, можно с принтами в ключевых местах. Буду очень признателен, да и наверное не только я.&lt;/p&gt;
</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
  <entry>
    <id>https://stocksharp.com/posts/m/15942/</id>
    <title type="text">И ещё вопрос про IsCandleBullishOrBearish() В документации написано &amp;quot;True, если бычья, false, если м...</title>
    <published>2012-01-25T17:54:49Z</published>
    <updated>2012-01-25T17:54:49Z</updated>
    <author>
      <name>risty</name>
      <uri>https://stocksharp.com/users/6257/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <content type="html">&lt;p&gt;И ещё вопрос про &lt;a href="http://stocksharp.com/doc/html/M_StockSharp_Algo_Candles_CandleHelper_IsCandleBullishOrBearish.htm"&gt;IsCandleBullishOrBearish()&lt;/a&gt;
В документации написано &lt;em&gt;&amp;quot;True, если бычья, false, если медвежья, null - ни то, ни другое.&amp;quot;&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;var SmallCandels = _candleManager.GetTimeFrameCandles(Security, _SmallTF, SmallCandelsNumber);

foreach (var SmallCandel in SmallCandels)
            {
                
                if (SmallCandel.IsCandleBullishOrBearish() == false) 
                { 
                    this.AddLog(new LogMessage(this, Trader.MarketTime, ErrorTypes.None,
                                   &amp;quot;МЕДВЕЖЬЯ _SmallTF = {0}, SmallCandel.Time = {1}, OpenPrice = {2}, ClosePrice = {3}&amp;quot;,
                                   _SmallTF, SmallCandel.Time, SmallCandel.OpenPrice, SmallCandel.ClosePrice));
                }

                if (SmallCandel.IsCandleBullishOrBearish() == true)
                {
                    this.AddLog(new LogMessage(this, Trader.MarketTime, ErrorTypes.None,
                                   &amp;quot;БЫЧЬЯ _SmallTF = {0}, SmallCandel.Time = {1}, OpenPrice = {2}, ClosePrice = {3}&amp;quot;,
                                   _SmallTF, SmallCandel.Time, SmallCandel.OpenPrice, SmallCandel.ClosePrice));
                }
                

            }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Не возвращает ни одной медвежьей свечки при прогоне на пяти днях истории(дальше остановил тест).
Бычьи возвращаются.
Это баг или я что-то не так понял в описании метода ?&lt;/p&gt;
</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
  <entry>
    <id>https://stocksharp.com/posts/m/15904/</id>
    <title type="text">Есть вопрос про свечки, надеюсь в тему. Допустим у нас есть какое-то NewMyTrade.Time Я хочу получить...</title>
    <published>2012-01-24T19:48:08Z</published>
    <updated>2012-01-24T19:48:49Z</updated>
    <author>
      <name>risty</name>
      <uri>https://stocksharp.com/users/6257/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <content type="html">&lt;p&gt;Есть вопрос про свечки, надеюсь в тему.
Допустим у нас есть какое-то NewMyTrade.Time
Я хочу получить свечку с:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;candle.Time = NewMyTrade.Time - new TimeSpan (0,5,11);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;и таймфреймом&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;candle.Timeframe = new TimeSpan (0,5,11);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;т.е. получить свечку от произвольного момента в прошлом(для примера взято 5:11) до NewMyTrade.Time, причем при каждом новом NewMyTrade.Time произвольный момент в прошлом меняется.&lt;/p&gt;
&lt;p&gt;Как это элегантнее всего сделать ?&lt;/p&gt;
</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
  <entry>
    <id>https://stocksharp.com/posts/m/15584/</id>
    <title type="text">Church: Вот мой пример. Комментарии может быть даже слишком подробные - это те моменты, в которые я ...</title>
    <published>2012-01-12T12:25:19Z</published>
    <updated>2012-01-12T12:25:19Z</updated>
    <author>
      <name>OvcharenkoVI</name>
      <uri>https://stocksharp.com/users/390/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="@message(10620)" rel="nofollow" target="_blank"&gt;Church&lt;/a&gt;:&lt;/strong&gt;
Вот мой пример. Комментарии может быть даже слишком подробные - это те моменты, в которые я утыкался сам.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;/*&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Каркас событийной стратегии на индикаторах&lt;/li&gt;
&lt;li&gt;&lt;/li&gt;
&lt;li&gt;Сверху в стратегию передаются сами индикаторы. Обязанность по прогону индикаторов по истории и по их обновлению ложится на тот код, в котором стратегия создается.&lt;/li&gt;
&lt;li&gt;Для свечных индюков это событие CandleManager.CandlesFinished.&lt;/li&gt;
&lt;li&gt;Такой подход позволяет использовать легко использовать разные стратегии, временно останавливать стратегию через .Stop() (например, перед клирингом или новостями) и снова запускать через .Start()&lt;/li&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*/&lt;/p&gt;
&lt;p&gt;using System;
using System.Collections.Generic;&lt;/p&gt;
&lt;p&gt;using StockSharp.Algo;
using StockSharp.Algo.Candles;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;&lt;/p&gt;
&lt;p&gt;public class MyStrategy : Strategy
{
#region Объявление переменных&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;//private readonly &amp;lt;Набор индикаторов из StockSharp.Algo.Indicators&amp;gt;

private int Position = 0;
private decimal EntrySlip = 0.0m;
private decimal ExitSlip = 1000.0m;

/// &amp;lt;summary&amp;gt;
/// Проскальзывание при входе
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;remarks&amp;gt;Необходимо задавать при инициализации стратегии, иначе будет равно 0.&amp;lt;/remarks&amp;gt;
public decimal EntrySlippage { set { EntrySlip = value; } get { return EntrySlip; } }
/// &amp;lt;summary&amp;gt;
/// Проскальзывание при выходе
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;remarks&amp;gt;Необходимо задавать при инициализации стратегии, иначе будет равно 1000.&amp;lt;/remarks&amp;gt;
public decimal ExitSlippage { set { ExitSlip = value; } get { return ExitSlip; } }

// Стопы хранятся в виде переменных, а не стоп-ордеров - для совместимости с тестером
private decimal LongStopLoss;
private decimal ShortStopLoss;

private bool InTrade = false;
private bool IsExited = false;
#endregion

// Конструктор
public MyStrategy(/*&amp;lt;индикаторы&amp;gt;*/)
{
    this.Name = &amp;quot;...&amp;quot;;
    //&amp;lt;Передача индикаторов в тело стратегии&amp;gt;
}

protected override void OnStarting()
{
    // Подписка на свои трейды - для расчета и обновления позиции
    this.NewMyTrades += RecalculatePosition;

    // Если до запуска стратегии не был переопределен объем, объем будет 1.
    if (this.Volume == 0) this.Volume = 1;

    // Подписка на новые тики - для осуществления основных действий
    this
        .When(Security.SecurityNewTrades())
        .Do(Process);
                
    // Если основные действия производятся по окончанию свечек, то придется передавать в стратегию CandleToken и CandleManager
    // и подписываться на события CandleManager.CandlesFinished или создавать правила на CandleToken.CandlesFinished

    base.OnStarting();
}
protected override void OnStopping()
{
    // Отписываемся от событий
    this.Rules.Remove(Security.SecurityNewTrades());
    this.NewMyTrades -= RecalculatePosition;

    // Ликвидируем позицию
    if (Position &amp;gt; 0)
    {
        var order = CreateOrder(OrderDirections.Sell, this.Security.BestAsk.Price - ExitSlip, Position);
        RegisterOrder(order);
    }
    else if (Position &amp;lt; 0)
    {
        var order = CreateOrder(OrderDirections.Buy, this.Security.BestAsk.Price + ExitSlip, -Position);
        RegisterOrder(order);
    }

    base.OnStopping();
}


// Расчет позиции
/// &amp;lt;summary&amp;gt;
/// Пересчет позиции при новых собственных сделках
/// &amp;lt;/summary&amp;gt;
private void RecalculatePosition(IEnumerable&amp;lt;MyTrade&amp;gt; trades)
{
    foreach (var trade in trades)
    {
        if (trade.Order.Direction == OrderDirections.Buy)
            Position += trade.Trade.Volume;
        if (trade.Order.Direction == OrderDirections.Sell)
            Position -= trade.Trade.Volume;
    }
}


// Главный обработчик (изменение котировок). Если сигналы должны генерироваться только по окончанию свечки, то этот код надо переместить в метод, 
// который вызывается в ответ на событие CandleManager.CandleFinished.
/// &amp;lt;summary&amp;gt;
/// Центральный метод - обработка новых тиков
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;remarks&amp;gt;Проверка условий входа/выхода с учетом текущей позиции; Генерация сигналов.&amp;lt;/remarks&amp;gt;
private void Process()
{
    if (!IsExited) // а вдруг уже выходим, но позиция еще не успела пересчитаться?
    {
        if (ExitLongSignal() &amp;amp;&amp;amp; (Position &amp;gt; 0))
            ExitLong(this.Security.BestBid.Price);

        if (ExitShortSignal() &amp;amp;&amp;amp; (Position &amp;lt; 0))
            ExitShort(this.Security.BestAsk.Price);
    }

    if (!InTrade) // не более одного входа на свечке
    {
        if (GoLongSignal() &amp;amp;&amp;amp; (Position &amp;lt;= 0))
            GoLong(this.Security.BestAsk.Price);

        if (GoShortSignal() &amp;amp;&amp;amp; (Position &amp;gt;= 0))
            GoShort(this.Security.BestBid.Price);
    }
}

// Логика - проверка условий входа/выхода

// Идти ли в лонг на текущем тике? 
private bool GoLongSignal()
{
    if (this.Security.LastTrade != null)
        return (/*логическое условие входа в лонг, например ema1.Value&amp;gt;ema2.Value*/);
    else
        return false;
}
private bool GoShortSignal()
{
    if (this.Security.LastTrade != null)
        return (/*логическое условие входа в шорт, например ema1.Value&amp;lt;ema2.Value*/);
    else
        return false;
}
private bool ExitLongSignal()
{
    if (this.Security.LastTrade != null)
        return ((this.Security.LastTrade.Price &amp;lt; LongStopLoss) || (/*логическое условие для выхода из лонга*/));
    else
        return false;
}
private bool ExitShortSignal()
{
    if (this.Security.LastTrade != null)
        return ((this.Security.LastTrade.Price &amp;gt; ShortStopLoss) || (/*логическое условие для выхода из шорта*/));
    else
        return false;
}

// Исполнение
private void GoLong(decimal Price)
{
    var order = CreateOrder(OrderDirections.Buy, this.Security.BestAsk.Price + EntrySlip, this.Volume); // настроить по вкусу :)
    order.ExecutionCondition = OrderExecutionConditions.FillOrCancel; 
    RegisterOrder(order);
    LongStopLoss = CalcStopLoss(OrderDirections.Buy, Price);
    this.AddInfoLog(&amp;quot;=&amp;gt; ENTER LONG.&amp;quot;);
    InTrade = true;
    IsExited = false;
}
private void GoShort(decimal Price)
{
    var order = CreateOrder(OrderDirections.Sell, this.Security.BestBid.Price - EntrySlip, this.Volume);
    order.ExecutionCondition = OrderExecutionConditions.FillOrCancel;
    RegisterOrder(order);
    ShortStopLoss = CalcStopLoss(OrderDirections.Sell, Price);
    this.AddInfoLog(&amp;quot;=&amp;gt; ENTER SHORT.&amp;quot;);
    InTrade = true;
    IsExited = false;
}
private void ExitLong(decimal Price)
{
    var order = CreateOrder(OrderDirections.Sell, this.Security.BestBid.Price - ExitSlip, this.Volume);
    order.ExecutionCondition = OrderExecutionConditions.FillOrCancel;
    RegisterOrder(order);
    this.AddInfoLog(&amp;quot;&amp;lt;= EXIT LONG.&amp;quot;);
    InTrade = false;
    IsExited = true;
}
private void ExitShort(decimal Price)
{
    var order = CreateOrder(OrderDirections.Buy, this.Security.BestAsk.Price + ExitSlip, this.Volume);
    RegisterOrder(order);
    this.AddInfoLog(&amp;quot;&amp;lt;= EXIT SHORT.&amp;quot;);
    InTrade = false;
    IsExited = true;
}

// Расчет изначального стопа
/// &amp;lt;summary&amp;gt;
/// Расчет изначального стопа на основе ATR
/// &amp;lt;/summary&amp;gt;
private decimal CalcStopLoss(OrderDirections direct, decimal tradePrice)
{
    return /*расчитанный тем или иным образом стоплосс*/
}

/// &amp;lt;summary&amp;gt;
/// Сохраняет в лог отчет о текущем состоянии важнейших параметров стратегии.
/// &amp;lt;/summary&amp;gt;
public void PrintStrategyState()
{
    this.AddInfoLog(&amp;quot; –––––––––––– [Status report] –––––––––––– &amp;quot;);
    this.AddInfoLog(&amp;quot;|  Current P/L = &amp;quot; + this.PnLManager.PnL.ToString());
    this.AddInfoLog(&amp;quot;|  Position = {0}&amp;quot;, Position);
    // Добавить инфы по вкусу.
    this.AddInfoLog(&amp;quot; –––––––––––––– [End report] –––––––––––––– &amp;quot;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
Очень полезный пример, наглядная реализация стопов без использования StopLossStrategy помогла
&lt;/code&gt;&lt;/pre&gt;
</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
  <entry>
    <id>https://stocksharp.com/posts/m/10669/</id>
    <title type="text">Сделал эту запись в конструкторе, оверрайд OnStopping удалил. При остановке стратгии при отрытой поз...</title>
    <published>2011-08-28T15:21:42Z</published>
    <updated>2011-08-28T15:23:45Z</updated>
    <author>
      <name>Church</name>
      <uri>https://stocksharp.com/users/459/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <content type="html">&lt;p&gt;Сделал эту запись в конструкторе, оверрайд OnStopping удалил. При остановке стратгии при отрытой позиции она не закрывается. PositionManager.Position показывает отличное от нуля число, как и таблица в квике. Кроме удаления OnStopping все аналогично коду выше.&lt;/p&gt;
</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
  <entry>
    <id>https://stocksharp.com/posts/m/10665/</id>
    <title type="text">Church: Кстати, this.When(this.Stopping()).ClosePosition() у меня не работает Чуть подробнее. Church...</title>
    <published>2011-08-28T11:53:18Z</published>
    <updated>2011-08-28T11:53:18Z</updated>
    <author>
      <name>Mikhail Sukhov</name>
      <uri>https://stocksharp.com/users/201/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="@message(10646)" rel="nofollow" target="_blank"&gt;Church&lt;/a&gt;:&lt;/strong&gt;
Кстати, this.When(this.Stopping()).ClosePosition() у меня не работает&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Чуть подробнее.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="@message(10646)" rel="nofollow" target="_blank"&gt;Church&lt;/a&gt;:&lt;/strong&gt;
а ClosePositionHandler я не могу найти даже через хэлп.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Конечно нет. Это должен быть обработчик в вашем коде.&lt;/p&gt;
</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
  <entry>
    <id>https://stocksharp.com/posts/m/10646/</id>
    <title type="text">Кстати, this.When(this.Stopping()).ClosePosition() у меня не работает, а ClosePositionHandler я не м...</title>
    <published>2011-08-26T12:02:42Z</published>
    <updated>2011-08-26T12:02:42Z</updated>
    <author>
      <name>Church</name>
      <uri>https://stocksharp.com/users/459/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <content type="html">&lt;p&gt;Кстати, this.When(this.Stopping()).ClosePosition() у меня не работает, а ClosePositionHandler я не могу найти даже через хэлп.&lt;/p&gt;
</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
  <entry>
    <id>https://stocksharp.com/posts/m/10632/</id>
    <title type="text">Михаил, спасибо! TraderHelper оказался очень полезным классом. :) Я с радостью как-нибудь поучаствую...</title>
    <published>2011-08-25T20:04:54Z</published>
    <updated>2011-08-25T20:04:54Z</updated>
    <author>
      <name>Church</name>
      <uri>https://stocksharp.com/users/459/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <content type="html">&lt;p&gt;Михаил, спасибо! TraderHelper оказался очень полезным классом. :)&lt;/p&gt;
&lt;p&gt;Я с радостью как-нибудь поучаствую в проекте, только одна проблема - у меня всего три недели опыта серьезного программирования.&lt;/p&gt;
&lt;p&gt;Если позволите, пара вопросов.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Как переделать Process под событийную модель, вроде и так уже событийно до тиков. :)
Сделать делать одноразовые правила типа LastTradePriceLess/More и обновлять на свечках? А в чем будет преимущество перед Process - высвобождение ресурсов?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Раз вы сделали специальную механику правил-действий, значит стандартная событийная модель чем-то не устраивала. Можете вкратце рассказать философию правил-действий и как их лучше всего использовать?&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
  <entry>
    <id>https://stocksharp.com/posts/m/10625/</id>
    <title type="text">Хотите получать такие советы регулярно? Прочитайте надпись и спросите меня, чем вы можете помочь про...</title>
    <published>2011-08-25T18:05:08Z</published>
    <updated>2011-08-25T18:05:08Z</updated>
    <author>
      <name>Mikhail Sukhov</name>
      <uri>https://stocksharp.com/users/201/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <content type="html">&lt;p&gt;Хотите получать такие советы регулярно? Прочитайте надпись и спросите меня, чем вы можете помочь проекту. Помогая проекту, проект в лице людей с голубыми никами будет помогать и вам.[cool]&lt;/p&gt;
</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
  <entry>
    <id>https://stocksharp.com/posts/m/10624/</id>
    <title type="text">Аналогичные советы, что я дал Church ODE0� Заменяется на более элегантное: this. When(_candleManager...</title>
    <published>2011-08-25T18:02:58Z</published>
    <updated>2011-08-25T18:02:58Z</updated>
    <author>
      <name>Mikhail Sukhov</name>
      <uri>https://stocksharp.com/users/201/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <content type="html">&lt;p&gt;Аналогичные советы, что я дал Church&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;ODE0�
Заменяется на более элегантное:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;this.
            When(_candleManager.Tokens.ElementAt(0).NewCandles()). // лучше токен вообще хранить как свойство стратегии
            Do(action);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;А еще лучше передавать новые свечки в обработчик:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;this.
            When(_candleManager.Tokens.ElementAt(0).NewCandles()). // лучше токен вообще хранить как свойство стратегии
            Do&amp;lt;IEnumerable&amp;lt;Candle&amp;gt;&amp;gt;(action);
&lt;/code&gt;&lt;/pre&gt;
&lt;ol start="2"&gt;
&lt;li&gt;GetCandlesCurrentAndPrev - Посмотрите на метод ICandleContainer.GetCandle(index)&lt;/li&gt;
&lt;li&gt;action. Писать в стратегии парсинг файла плохой стиль. Считайте файл где-то еще, и передавайте в стратегию уже полученные данные.&lt;/li&gt;
&lt;li&gt;ODE3�
вот так тоже будет работать:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;AddErrorLog(orderFail.Error.Message);
&lt;/code&gt;&lt;/pre&gt;
</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
  <entry>
    <id>https://stocksharp.com/posts/m/10623/</id>
    <title type="text">Полезно своими наработками делиться с товарищем по цеху. Вы привели свой код, а я увидел в нем неточ...</title>
    <published>2011-08-25T17:55:55Z</published>
    <updated>2011-08-25T17:55:55Z</updated>
    <author>
      <name>Mikhail Sukhov</name>
      <uri>https://stocksharp.com/users/201/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <content type="html">&lt;p&gt;Полезно своими наработками делиться с товарищем по цеху. Вы привели свой код, а я увидел в нем неточности. Ловите бесплатные напутствия [laugh]:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Security.SecurityNewTrades() каждый раз создает новое правило. Первый раз вы делаете все правильно, добавляя его в свою коллекцию. Второй раз в OnStopping вы не удаляете старой правило, а пытаетесь удалить свеже созданное. Ошибки в этом случае не возникает. Поэтому вы и не находите эту ошибку.&lt;/li&gt;
&lt;li&gt;Правила, если им не делать критерий остановки, по умолчанию останавливаются сами и удаляются так же из коллекции правил. Нет необходимости это делать принудительно.&lt;/li&gt;
&lt;li&gt;Закрытие позиции лучше так же делать через правила:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;
this.When(this.Stopping())
.ClosePosition();

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;или&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;
this.When(this.Stopping())
.Do(ClosePositionHandler);

&lt;/code&gt;&lt;/pre&gt;
&lt;ol start="4"&gt;
&lt;li&gt;RecalculatePosition == TraderHelper.GetPosition&lt;/li&gt;
&lt;li&gt;Метод Process напрашивается сам на событийных подход&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Как совет, посмотрите, какие методы присутствуют в TraderHelper + StrategyRuleConditionHelper.&lt;/p&gt;
</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
  <entry>
    <id>https://stocksharp.com/posts/m/10620/</id>
    <title type="text">Вот мой пример. Комментарии может быть даже слишком подробные - это те моменты, в которые я утыкался...</title>
    <published>2011-08-25T15:40:56Z</published>
    <updated>2011-08-25T15:42:54Z</updated>
    <author>
      <name>Church</name>
      <uri>https://stocksharp.com/users/459/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <content type="html">&lt;p&gt;Вот мой пример. Комментарии может быть даже слишком подробные - это те моменты, в которые я утыкался сам.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;/*
 * Каркас событийной стратегии на индикаторах
 * 
 * Сверху в стратегию передаются сами индикаторы. Обязанность по прогону индикаторов по истории и по их обновлению ложится на тот код, в котором стратегия создается.
 * Для свечных индюков это событие CandleManager.CandlesFinished.
 * Такой подход позволяет использовать легко использовать разные стратегии, временно останавливать стратегию через .Stop() (например, перед клирингом или новостями) и снова запускать через .Start()
 * 
 */ 

using System;
using System.Collections.Generic;

using StockSharp.Algo;
using StockSharp.Algo.Candles;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;

public class MyStrategy : Strategy
{
    #region Объявление переменных

    //private readonly &amp;lt;Набор индикаторов из StockSharp.Algo.Indicators&amp;gt;

    private int Position = 0;
    private decimal EntrySlip = 0.0m;
    private decimal ExitSlip = 1000.0m;

    /// &amp;lt;summary&amp;gt;
    /// Проскальзывание при входе
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;remarks&amp;gt;Необходимо задавать при инициализации стратегии, иначе будет равно 0.&amp;lt;/remarks&amp;gt;
    public decimal EntrySlippage { set { EntrySlip = value; } get { return EntrySlip; } }
    /// &amp;lt;summary&amp;gt;
    /// Проскальзывание при выходе
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;remarks&amp;gt;Необходимо задавать при инициализации стратегии, иначе будет равно 1000.&amp;lt;/remarks&amp;gt;
    public decimal ExitSlippage { set { ExitSlip = value; } get { return ExitSlip; } }

    // Стопы хранятся в виде переменных, а не стоп-ордеров - для совместимости с тестером
    private decimal LongStopLoss;
    private decimal ShortStopLoss;

    private bool InTrade = false;
    private bool IsExited = false;
    #endregion

    // Конструктор
    public MyStrategy(/*&amp;lt;индикаторы&amp;gt;*/)
    {
        this.Name = &amp;quot;...&amp;quot;;
        //&amp;lt;Передача индикаторов в тело стратегии&amp;gt;
    }

    protected override void OnStarting()
    {
        // Подписка на свои трейды - для расчета и обновления позиции
        this.NewMyTrades += RecalculatePosition;

        // Если до запуска стратегии не был переопределен объем, объем будет 1.
        if (this.Volume == 0) this.Volume = 1;

        // Подписка на новые тики - для осуществления основных действий
        this
            .When(Security.SecurityNewTrades())
            .Do(Process);
                    
        // Если основные действия производятся по окончанию свечек, то придется передавать в стратегию CandleToken и CandleManager
        // и подписываться на события CandleManager.CandlesFinished или создавать правила на CandleToken.CandlesFinished

        base.OnStarting();
    }
    protected override void OnStopping()
    {
        // Отписываемся от событий
        this.Rules.Remove(Security.SecurityNewTrades());
        this.NewMyTrades -= RecalculatePosition;

        // Ликвидируем позицию
        if (Position &amp;gt; 0)
        {
            var order = CreateOrder(OrderDirections.Sell, this.Security.BestAsk.Price - ExitSlip, Position);
            RegisterOrder(order);
        }
        else if (Position &amp;lt; 0)
        {
            var order = CreateOrder(OrderDirections.Buy, this.Security.BestAsk.Price + ExitSlip, -Position);
            RegisterOrder(order);
        }

        base.OnStopping();
    }


    // Расчет позиции
    /// &amp;lt;summary&amp;gt;
    /// Пересчет позиции при новых собственных сделках
    /// &amp;lt;/summary&amp;gt;
    private void RecalculatePosition(IEnumerable&amp;lt;MyTrade&amp;gt; trades)
    {
        foreach (var trade in trades)
        {
            if (trade.Order.Direction == OrderDirections.Buy)
                Position += trade.Trade.Volume;
            if (trade.Order.Direction == OrderDirections.Sell)
                Position -= trade.Trade.Volume;
        }
    }


    // Главный обработчик (изменение котировок). Если сигналы должны генерироваться только по окончанию свечки, то этот код надо переместить в метод, 
    // который вызывается в ответ на событие CandleManager.CandleFinished.
    /// &amp;lt;summary&amp;gt;
    /// Центральный метод - обработка новых тиков
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;remarks&amp;gt;Проверка условий входа/выхода с учетом текущей позиции; Генерация сигналов.&amp;lt;/remarks&amp;gt;
    private void Process()
    {
        if (!IsExited) // а вдруг уже выходим, но позиция еще не успела пересчитаться?
        {
            if (ExitLongSignal() &amp;amp;&amp;amp; (Position &amp;gt; 0))
                ExitLong(this.Security.BestBid.Price);

            if (ExitShortSignal() &amp;amp;&amp;amp; (Position &amp;lt; 0))
                ExitShort(this.Security.BestAsk.Price);
        }

        if (!InTrade) // не более одного входа на свечке
        {
            if (GoLongSignal() &amp;amp;&amp;amp; (Position &amp;lt;= 0))
                GoLong(this.Security.BestAsk.Price);

            if (GoShortSignal() &amp;amp;&amp;amp; (Position &amp;gt;= 0))
                GoShort(this.Security.BestBid.Price);
        }
    }

    // Логика - проверка условий входа/выхода

    // Идти ли в лонг на текущем тике? 
    private bool GoLongSignal()
    {
        if (this.Security.LastTrade != null)
            return (/*логическое условие входа в лонг, например ema1.Value&amp;gt;ema2.Value*/);
        else
            return false;
    }
    private bool GoShortSignal()
    {
        if (this.Security.LastTrade != null)
            return (/*логическое условие входа в шорт, например ema1.Value&amp;lt;ema2.Value*/);
        else
            return false;
    }
    private bool ExitLongSignal()
    {
        if (this.Security.LastTrade != null)
            return ((this.Security.LastTrade.Price &amp;lt; LongStopLoss) || (/*логическое условие для выхода из лонга*/));
        else
            return false;
    }
    private bool ExitShortSignal()
    {
        if (this.Security.LastTrade != null)
            return ((this.Security.LastTrade.Price &amp;gt; ShortStopLoss) || (/*логическое условие для выхода из шорта*/));
        else
            return false;
    }

    // Исполнение
    private void GoLong(decimal Price)
    {
        var order = CreateOrder(OrderDirections.Buy, this.Security.BestAsk.Price + EntrySlip, this.Volume); // настроить по вкусу :)
        order.ExecutionCondition = OrderExecutionConditions.FillOrCancel; 
        RegisterOrder(order);
        LongStopLoss = CalcStopLoss(OrderDirections.Buy, Price);
        this.AddInfoLog(&amp;quot;=&amp;gt; ENTER LONG.&amp;quot;);
        InTrade = true;
        IsExited = false;
    }
    private void GoShort(decimal Price)
    {
        var order = CreateOrder(OrderDirections.Sell, this.Security.BestBid.Price - EntrySlip, this.Volume);
        order.ExecutionCondition = OrderExecutionConditions.FillOrCancel;
        RegisterOrder(order);
        ShortStopLoss = CalcStopLoss(OrderDirections.Sell, Price);
        this.AddInfoLog(&amp;quot;=&amp;gt; ENTER SHORT.&amp;quot;);
        InTrade = true;
        IsExited = false;
    }
    private void ExitLong(decimal Price)
    {
        var order = CreateOrder(OrderDirections.Sell, this.Security.BestBid.Price - ExitSlip, this.Volume);
        order.ExecutionCondition = OrderExecutionConditions.FillOrCancel;
        RegisterOrder(order);
        this.AddInfoLog(&amp;quot;&amp;lt;= EXIT LONG.&amp;quot;);
        InTrade = false;
        IsExited = true;
    }
    private void ExitShort(decimal Price)
    {
        var order = CreateOrder(OrderDirections.Buy, this.Security.BestAsk.Price + ExitSlip, this.Volume);
        RegisterOrder(order);
        this.AddInfoLog(&amp;quot;&amp;lt;= EXIT SHORT.&amp;quot;);
        InTrade = false;
        IsExited = true;
    }

    // Расчет изначального стопа
    /// &amp;lt;summary&amp;gt;
    /// Расчет изначального стопа на основе ATR
    /// &amp;lt;/summary&amp;gt;
    private decimal CalcStopLoss(OrderDirections direct, decimal tradePrice)
    {
        return /*расчитанный тем или иным образом стоплосс*/
    }

    /// &amp;lt;summary&amp;gt;
    /// Сохраняет в лог отчет о текущем состоянии важнейших параметров стратегии.
    /// &amp;lt;/summary&amp;gt;
    public void PrintStrategyState()
    {
        this.AddInfoLog(&amp;quot; –––––––––––– [Status report] –––––––––––– &amp;quot;);
        this.AddInfoLog(&amp;quot;|  Current P/L = &amp;quot; + this.PnLManager.PnL.ToString());
        this.AddInfoLog(&amp;quot;|  Position = {0}&amp;quot;, Position);
        // Добавить инфы по вкусу.
        this.AddInfoLog(&amp;quot; –––––––––––––– [End report] –––––––––––––– &amp;quot;);
    }
}
&lt;/code&gt;&lt;/pre&gt;
</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
  <entry>
    <id>https://stocksharp.com/posts/m/10569/</id>
    <title type="text">Что-то вроде этого: using System; using System.Collections.Generic; using System.Configuration; usin...</title>
    <published>2011-08-24T07:27:19Z</published>
    <updated>2011-08-24T07:27:19Z</updated>
    <author>
      <name>freelancer</name>
      <uri>https://stocksharp.com/users/28572/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <content type="html">&lt;p&gt;Что-то вроде этого:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;using System;
using System.Collections.Generic;
using System.Configuration;
using System.Globalization;
using System.IO;
using System.Linq;
using Ecng.Common;
using Ecng.ComponentModel;
using MoreLinq;
using StockSharp.Algo;
using StockSharp.Algo.Candles;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Quik;

namespace MyRobot
{
    class MyStrategyAction : Strategy
    {
        private readonly CandleManager _candleManager;
        private readonly TimeSpan _timeFrame;

        private struct CandlesCurrentAndPrev
        {
            public TimeFrameCandle CandlesCurrent;
            public TimeFrameCandle CandlesPrev;
        }

        private CandlesCurrentAndPrev GetCandlesCurrentAndPrev(CandleManager candleManager, TimeSpan timeFrame)
        {
            CandlesCurrentAndPrev c = new CandlesCurrentAndPrev();

            c.CandlesCurrent = candleManager.GetLastTimeFrameCandle(Security, timeFrame);
            c.CandlesPrev = candleManager.GetTimeFrameCandle(Security, timeFrame, c.CandlesCurrent.Time - timeFrame);

            return c;
        }
        
        public MyStrategyAction(CandleManager candleManager, TimeSpan timeFrame)
        {
            _candleManager = candleManager;

            _timeFrame = timeFrame;

            this.OrderFailed += orderFail =&amp;gt; AddErrorLog(orderFail.Error.Message, new object[] { });
            this.StopOrderFailed += stopOrderFail =&amp;gt; AddErrorLog(stopOrderFail.Error.Message, new object[] { });
        }

        private void action()
        {
            CandlesCurrentAndPrev candlesCurrentAndPrev = GetCandlesCurrentAndPrev(_candleManager, _timeFrame);

            var candleCurrent = candlesCurrentAndPrev.CandlesCurrent;

            if ((candleCurrent.Time - Trader.MarketTime).Duration() &amp;gt; new TimeSpan(0, 0, 20))
                return;

            if (candleCurrent == null)
            {
                AddWarningLog(&amp;quot;Текущая свеча = null&amp;quot;, new object[] { });
                return;
            }

            var candle = candlesCurrentAndPrev.CandlesPrev;
            
            var candlesFromFile = File.ReadAllLines(&amp;quot;RTS_15MIN.txt&amp;quot;).Select(line =&amp;gt;
            {
                var parts = line.Split(',');
                var time = DateTime.ParseExact(parts[0] + parts[1], &amp;quot;yyyyMMddHHmmss&amp;quot;, CultureInfo.InvariantCulture);
                return new TimeFrameCandle
                {
                    OpenPrice = parts[2].Replace(&amp;quot;.00000&amp;quot;, &amp;quot;&amp;quot;).To&amp;lt;decimal&amp;gt;(),
                    HighPrice = parts[3].Replace(&amp;quot;.00000&amp;quot;, &amp;quot;&amp;quot;).To&amp;lt;decimal&amp;gt;(),
                    LowPrice = parts[4].Replace(&amp;quot;.00000&amp;quot;, &amp;quot;&amp;quot;).To&amp;lt;decimal&amp;gt;(),
                    ClosePrice = parts[5].Replace(&amp;quot;.00000&amp;quot;, &amp;quot;&amp;quot;).To&amp;lt;decimal&amp;gt;(),
                    TimeFrame = _timeFrame,
                    Time = time,
                    TotalVolume = parts[6].To&amp;lt;int&amp;gt;(),
                    Security = this.Security,
                };
            });

            var candles = _candleManager.GetTimeFrameCandles(Security, _timeFrame, 1000).Take(_candleManager.GetTimeFrameCandles(Security, _timeFrame, 1000).Count() - 1);

            candles = candlesFromFile.Concat(candles).DistinctBy(t =&amp;gt; t.Time);            

            #region Генерация сигналов

            
            #endregion

            #region Выполнение сигналов

            
            #endregion
        }

        protected override void OnStarting()
        {
            if (_candleManager.Tokens.Count() == 0)
            {
                AddErrorLog(&amp;quot;_candleManager.Tokens.Count() = 0&amp;quot;, new object[] { });
                return;
            }

            this.
            When(StrategyRuleConditionHelper.NewCandles(_candleManager.Tokens.ElementAt(0))).
            Do(action);

            base.OnStarting();
        }

        protected override void DisposeManaged()
        {
            base.DisposeManaged();
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
  <entry>
    <id>https://stocksharp.com/posts/m/10552/</id>
    <title type="text">Church: Просим здешних товарищей - выложите, пожалуйста, каркас (без логики) событийного алгоритма, ...</title>
    <published>2011-08-23T14:47:07Z</published>
    <updated>2011-08-23T14:47:07Z</updated>
    <author>
      <name>wakwak</name>
      <uri>https://stocksharp.com/users/403/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="@message(10322)" rel="nofollow" target="_blank"&gt;Church&lt;/a&gt;:&lt;/strong&gt;
Просим здешних товарищей - выложите, пожалуйста, каркас (без логики) событийного алгоритма, основанного на свечках!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;+1, было бы архиполезно!&lt;/p&gt;
</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
  <entry>
    <id>https://stocksharp.com/posts/m/10322/</id>
    <title type="text">Михаил, спасибо - я как-то забыл про оффлайновый хэлп. Просим здешних товарищей - выложите, пожалуйс...</title>
    <published>2011-08-15T09:58:13Z</published>
    <updated>2011-08-15T09:58:13Z</updated>
    <author>
      <name>Church</name>
      <uri>https://stocksharp.com/users/459/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <content type="html">&lt;p&gt;Михаил, спасибо - я как-то забыл про оффлайновый хэлп.&lt;/p&gt;
&lt;p&gt;Просим здешних товарищей - выложите, пожалуйста, каркас (без логики) событийного алгоритма, основанного на свечках!&lt;/p&gt;
</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
  <entry>
    <id>https://stocksharp.com/posts/m/10314/</id>
    <title type="text">Teddy: Да было бы не плохо выложить каркас робота по событийной модели.А то вроде бы утверждается чт...</title>
    <published>2011-08-14T14:26:05Z</published>
    <updated>2011-08-14T14:26:05Z</updated>
    <author>
      <name>Mikhail Sukhov</name>
      <uri>https://stocksharp.com/users/201/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="@message(10312)" rel="nofollow" target="_blank"&gt;Teddy&lt;/a&gt;:&lt;/strong&gt;
Да было бы не плохо выложить каркас робота по событийной модели.А то вроде бы утверждается что за основу теперь берётся событийная модель,а самого полноценного примера нет.
Думаю очень многие были бы благодарны ,особенно начинающие.
Спасибо.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;В разделе Событийная модель показан пример хеджирования опционов. Если он не нравится и нужен другой пример, то предлагаю попросить здешних товарищей о том, чтобы привели кусочек кода из своего робота. Я пример подал.&lt;/p&gt;
</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
  <entry>
    <id>https://stocksharp.com/posts/m/10312/</id>
    <title type="text">Да было бы не плохо выложить каркас робота по событийной модели.А то вроде бы утверждается что за ос...</title>
    <published>2011-08-14T14:16:59Z</published>
    <updated>2011-08-14T14:16:59Z</updated>
    <author>
      <name>Teddy</name>
      <uri>https://stocksharp.com/users/28056/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <content type="html">&lt;p&gt;Да было бы не плохо выложить каркас робота по событийной модели.А то вроде бы утверждается что за основу теперь берётся событийная модель,а самого полноценного примера нет.
Думаю очень многие были бы благодарны ,особенно начинающие.
Спасибо.&lt;/p&gt;
</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
  <entry>
    <id>https://stocksharp.com/posts/m/10310/</id>
    <title type="text">Church: Пытаюсь разобраться в том, как работает событийная стратегия на свечках. Насколько я могу по...</title>
    <published>2011-08-14T13:14:05Z</published>
    <updated>2011-08-14T13:14:05Z</updated>
    <author>
      <name>Mikhail Sukhov</name>
      <uri>https://stocksharp.com/users/201/</uri>
      <email>info@stocksharp.com</email>
    </author>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="@message(10309)" rel="nofollow" target="_blank"&gt;Church&lt;/a&gt;:&lt;/strong&gt;
Пытаюсь разобраться в том, как работает событийная стратегия на свечках. Насколько я могу понять, со времени выпуска документации механизмы изменились и описанные на форуме и в API .when.do конструкции на CandleToken'ах не работают, а без исходников понять почему - не получается.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Документация на сайте устарела, да. Но всегда существует оффлайн документация. Читайте ее. Она соответствует последней версии.&lt;/p&gt;
</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
</feed>