﻿<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type='text/css' href='https://stocksharp.ru/css/style.css'?>
<?xml-stylesheet type='text/css' href='https://stocksharp.ru/css/bbeditor.css'?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title type="html">Статьи. StockSharp</title>
  <id>https://stocksharp.ru/handlers/atom.ashx?category=articles&amp;page=14</id>
  <rights type="text">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  <updated>2026-07-03T20:16:22Z</updated>
  <logo>https://stocksharp.ru/images/logo.png</logo>
  <link href="https://stocksharp.ru/handlers/atom.ashx?category=articles&amp;page=14" rel="self" type="application/rss+xml" />
  <entry>
    <id>https://stocksharp.ru/topic/362/</id>
    <title type="text">Plaza 2. Торговые роботы с прямым доступом.</title>
    <published>2012-03-13T01:56:56Z</published>
    <updated>2012-12-17T15:07:20Z</updated>
    <author>
      <name>StockSharp</name>
      <uri>https://stocksharp.ru/users/341/</uri>
      <email>info@stocksharp.ru</email>
    </author>
    <category term="Программирование роботов" />
    <category term="API" />
    <category term="Примеры" />
    <category term="Plaza 2" />
    <category term="Торговые роботы" />
    <category term="Высокочастотная торговля" />
    <category term="HFT роботы" />
    <category term="Статьи" />
    <content type="html">&lt;p&gt;&lt;strong&gt;Вступление&lt;/strong&gt;
Краткое вступление о том, что такое прямой доступ к торгам для робота. Это значит, что ваш робот начинает  слать торговые сигналы на биржу, минуя всех посредников (брокера, промежуточное программное обеспечение и т.д.). Часто подобный  доступ ассоциируют с High Frequency Trading (далее, просто HFT) роботами, или, попросту говоря, высокочастотниками. Но HFT это не единственные “клиенты”, кому может быть удобен такой способ. Ниже ряд преимуществ и для обычного робота:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Отсутствие прослоек уменьшает технические риски.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Прямой доступ гарантирует торговлю только по правилам биржи, без накладывания дополнительных ограничений. Например, дополнительное ГО (гарантийному обеспечению), как правило.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Робот не привязан к какой-либо технологии доступа, кроме как к Plaza2.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Самая полная информация о маркет-данных. Например, order log (журнал заявок, поступающих от всех участников торгов).
&lt;strong&gt;Модель доступа&lt;/strong&gt;
Естественно, создание роботов под шлюз биржи – это только их программирование. На языке C#, С++, Delphi и т.д. – на чем больше опыт. Биржа дает свой программный интерфейс (далее, API), с помощью которого роботы и подключаются к торгам. Бывают 2 версии этого API, под 32 и 64 битные компьютеры. Лучше использовать под 64 бита, так как тогда робот не будет ограничен потреблением памяти. Для роботов, которые используют Plaza2 как один из источников данных, а так же сложные математические расчеты, проблема с доступной памятью наиболее актуальна.
Plaza2 API так же бывает однопоточной и многопоточной (STA, MTA). Лучше использовать MTA, так как в этом случае робот будет работать без временных зависаний (особенно проявляется при сильном движении на рынке), да и просто быстрее получать и отправлять данные. Написание робота под Plaza2 API требует глубоких познаний в программировании и специфике работы биржевых данных. Поэтому, для упрощения создания роботов можно использовать бесплатную библиотеку StockSharp. У нее есть ряд преимуществ перед обычным Plaza2 API:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Существенно упрощает и ускоряет процесс обучения написания роботов под Plaza2.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Позволяет включать режим эмуляции на реальных торгах (с реальной ликвидностью в стаканах).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Тестирование робота на исторических данных (единая среда как для написания робота, так и для тестирования).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://stocksharp.com/forum/2488/StockSharp-PlazaTrader-proshiel-siertifikatsiiu-RTS-MMVB/"&gt;Сертифицирована, что позволяет не проходить сертификацию у биржи, и получать сертификат автоматически&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Наличие стопов.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Не вносит никаких задержек, тоесть скорость работы точно такая же, как если писать робота напрямую под Plaza2 API (критично для HFT).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Открытый код.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Возможность подключать западные площадки.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="/file/101748/Plaza-2.png/" alt="plaza2" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Пример&lt;/strong&gt;
Вместо заключения небольшой пример того, как выглядит робот, торгующий через Plaza2.&lt;/p&gt;
&lt;p&gt;Подключение к торгам:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;var trader = new PlazaTrader();

Security rih2 = null;

trader.NewSecurities += securities =&amp;gt;
{
    // если RIH2 еще не появился, то пытаемся его найти
    if (rih2 == null)
        rih2 = securities.FirstOrDefault(s =&amp;gt; s.Id == &amp;quot;RIH2@RTS&amp;quot;);
};

// после успешного подключения запускаем экспорт
trader.Connected += trader.StartExport;

// подключаемся к торгам
trader.Connect();

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Небольшая стратегия, торгующая спредом фьючерса на индекс РТС:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;
class SpreadStrategy : Strategy
{
    private Order _order;
    private bool _canProcess;
    private OrderDirections _dir;

    protected override void OnStarting()
    {
        // подписываемся на правило изменения стакана
        this
            .When(Security.MarketDepthChanged())
            .Do(ProcessDepth);

        // добавляем автозащитную стратегию (автоматически выставляет тейк + стоп)
        ChildStrategies.Add(new AutoProtectiveStrategy());

        base.OnStarting();
    }

    private void ProcessDepth(MarketDepth depth)
    {
        // заявка пока еще не исполнена
        if (!_canProcess)
            return;

        // заявка исполнилась, но не исполнились стопы
        if (PositionManager.Position != 0)
            return;

        // создаем рыночную заявку (так как на FORTS нет такого понятия как рыночная заявка, то будет использована встречная цена в стакане)
        _order = this.CreateOrder(_dir, depth.GetMarketPrice(_dir));

        // в следующий раз будем открываться в другую сторону
        _dir = _dir.Invert();

        // запретить обработу стакана до тех пор, пока заявка не исполниться
        _canProcess = false;

        this
            .When(_order.Matched())
            .Do(() =&amp;gt; _canProcess = true);

        // отправляем на регистрацию
        RegisterOrder(_order);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Сухов Михаил
StockSharp Торговые роботы&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>https://stocksharp.ru/topic/361/</id>
    <title type="text">Торговые роботы Шаг 1. Тестирование торговой системы</title>
    <published>2012-03-18T14:34:45Z</published>
    <updated>2012-12-17T15:07:15Z</updated>
    <author>
      <name>StockSharp</name>
      <uri>https://stocksharp.ru/users/341/</uri>
      <email>info@stocksharp.ru</email>
    </author>
    <category term="Для начинающих" />
    <category term="Программирование роботов" />
    <category term="API" />
    <category term="Примеры" />
    <category term="Торговые роботы" />
    <category term="Статьи" />
    <content type="html">&lt;p&gt;Мне кажется, что эта статья будет больше всего интересна новичкам в алготрединге. Общаясь с людьми, недавно заинтересовавшимися торговыми роботами, я зачастую сталкивался с тем, что они не до конца понимают, что такое торговый робот и как его создают, поэтому я позволил себе немного рассуждений и пояснений на тему тестирования и создания робота. Если хотите освободить себя от моих рассуждений, переходите к главе - ТЕСТИРОВАНИЕ ТОРГОВОЙ СИСТЕМЫ,  Эта часть будет полностью посвящена практике тестирования и работе с платформой.&lt;/p&gt;
&lt;p&gt;Почему Торговые роботы.&lt;/p&gt;
&lt;p&gt;Часто, когда заходит разговор о торговом роботе, его главным преимуществом называют отсутствие психологических моментов в его работе. Нет страха, жадности или сомнений. Действительно, это существенные плюсы при торговле через торгового робота. Но главное преимущество торгового робота заключается в том, что мы можем протестировать алгоритм его работы на исторических данных. Таким образом, мы увидим,  работает наша торговая система или нет. Если работает, то мы увидим её слабые и сильные стороны и найдем способ улучшить доходность системы. Используя программы для тестирования торговых систем, мы пройдем эти шаги гораздо быстрее, чем, если бы мы проверяли нашу систему в режиме реального времени. Мы сэкономим наши силы, время и деньги. Поэтому тестирование торговых стратегий является очень важным этапом на пути создания торгового робота.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ВВЕДЕНИЕ&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Занимайтесь исследованием рынка&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;      Многие новички, приходя на рынок, не имеют четкой торговой системы для принятия решений – покупать или продавать бумагу; когда выходить из сделки, если она прибыльная; когда выходить из сделки, если он показывает убыток.  Новоиспеченный трейдер обучается прямо во время торгов – он принимает решения, основываясь на интуиции и на своём небольшом торговом опыте. Заработав на сделке, он запоминает определенный случай и старается применить его в будущем; получив убыток, он будет стараться избегать таких ситуаций. Но был ли тот случай, когда он смог заработать, действительной закономерностью или всего лишь единичным случаем из ста, когда ошибившись два раза, мы получили нужный результат? То же самое можно сказать по поводу отрицательного опыта – возможно, всё было сделано правильно, но именно в этот раз что-то сработало не так как надо, и мы не заработали. Начинающий трейдер не задается этим вопросом, и может взять за правило избегать прибыльных стратегий и следовать убыточным, основываясь на своём опыте. Причем те ситуации, которые  наблюдает новичок, складываются на основе множества факторов: новости, индикаторы (часто это не один индикатор),  наблюдение за стаканом, наблюдение за американским рынком, поведение самой цены. Человеку свойственно окружать себя тоннами информации, чтобы быть уверенным в своей правоте. Но, принимая решение на основе всех этих данных, и заработав или потеряв на сделке, как можно понять, благодаря чему именно мы заработали, и где была совершена ошибка, если мы потеряли деньги? Возникает множество сочетаний информации,  которой вы используете, вычленить нужные моменты из этой массы становиться трудно. Осознание своих ошибок и создание прибыльной торговой системы при таком подходе занимает огромное количество времени и стоит немалых денег.
         Итак, как же нам научиться зарабатывать на рынке, затратив при этом наименьшее количество времени и денег? Ответ настолько очевиден и прост, что я недоумеваю, почему этим занимается так мало людей! Чтобы научиться работать на рынке, обрести понимание рынка, надо заниматься его исследованием. Под исследованием я подразумеваю не просто наблюдение за рынком, а проверка сделанных выводов на основе прошлой истории, путем совершения бумажных сделок в прошлом, и анализом всех полученных результатов. Если вы недавно пришли на рынок, и у вас нет торговой системы, то вам необходимо придумать стратегию самим или взять за основу чужую систему. После чего требуется исследование, насколько хорошо эта система работает. Проверяя идею на истории, нам не надо ждать следующего дня, недели, месяца, чтобы увидеть первые результаты. Работая с историей, можно прогнать год торгов за несколько часов и узнать, какой результат можно ожидать от вашей системы. Так почему же этим занимается так мало людей? Проанализировав систему, вы лишаетесь иллюзий по поводу того, сможете ли вы заработать деньги, у вас не остается надежды на какое-то чудо. А также, работа на рынке лишается азарта, элемента игры. Мало кому хочется терять надежду на то, что “на рынке заработать просто”, не хочется превращать интересную игру в работу. Именно эти два желания – быстро разбогатеть и получить адреналин  являются причиной постоянного потока “мяса” на рынок. На фондовом рынке находиться не меньше мечтателей, чем в любом казино. 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;ПОДГОТОВКА К ТЕСТИРОВАНИЮ&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Выбор бумаги для тестирования&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; На фондовом рынке большое количество ценных бумаг и производных от этих ценных бумаг. У каждой бумаги своя специфика, свой характер движения. Это значит, что торговые системы, которые работают на одной бумаге, могут быть бесполезны на другой. Есть похожие по своему “характеру” бумаги, на которых будет работать один и тот же подход. Перед тем как создавать торговую систему, нам надо определиться, с каким инструментом мы будем работать. Советовать, чтобы на бумаге были сильные, резкие движения, или же наоборот, движения были плавные, нельзя. К какому рынку подойдет ваша система выясняется только тестированием. Желательно, чтобы бумага была ликвидная. Как вы позже сможете убедиться, потери при входе и выходе из-за проскальзывания значительно уменьшают прибыль и увеличивают убыток. Также стоит обращать внимание на комиссию – комиссия также может сильно сказываться на доходности системы. 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Свои системы мы создаем для фьючерса на индекс РТС. Он был выбран как наиболее ликвидный инструмент на российском рынке. Проскальзывание для систем устанавливается в размере 50п для входа и 50п для выхода. Реальное проскальзывание устанавливается опытным путем.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ТЕСТИРОВАНИЕ ТОРГОВОЙ СИСТЕМЫ. ПОДГОТОВКА ПЛАТФОРМЫ&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Выбор программы для тестирования стратегии&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Для графического отображения исторических данных и тестирования стратегии нам понадобится программа. Выбор программы зависит от разных факторов, каждая программа имеет свои плюсы и минусы. Ниже перечислены наиболее распространенные программы для разработки систем.
Omega Tradestation, Metastock, Amibroker, Wealth-Lab Developer
В апреле 2012 года выходит StockSharp Studio, и вы сможете создавать и тестировать системы в одном месте. А пока мы будем тестировать систему на другой платформе.&lt;/p&gt;
&lt;p&gt;Мы работаем на Wealth-Lab. Это один из признанных лидеров среди программ-тестировщиков. Основной его плюс – язык C#. Только ради этого плюса можно остановить свой выбор на этой программе. Данный язык – стандартный язык программирования, помощь по нему вы можете найти не столько на сайте программы wealth-lab, сколько на программистских сайтах и всемирно известных библиотеках (MSDN).&lt;/p&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;/ul&gt;
&lt;p&gt;&lt;strong&gt;После выбора программы нам необходимо загрузить котировки.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Скачать котировки можно с помощью Гидры  (   &lt;a href="http://stocksharp.com/doc/"&gt;http://stocksharp.com/doc/&lt;/a&gt;   Подробное описание работы с программой по ссылке  )&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Загрузка полученных данных в программу&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;На выходе мы получим текстовый файл с примерно следующим содержанием
ТФ 5 минут, тиккер – РТС.  Формат даты, как можно увидеть, ГГГГММДД, формат времени ЧЧММСС.
Разделитель – запятая.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;&amp;lt;DATE&amp;gt;,&amp;lt;TIME&amp;gt;,&amp;lt;OPEN&amp;gt;,&amp;lt;HIGH&amp;gt;,&amp;lt;LOW&amp;gt;,&amp;lt;CLOSE&amp;gt;,&amp;lt;VOL&amp;gt;
20090115,103000,55575.00000,55575.00000,55150.00000,55360.00000,7275
20090115,103500,55285.00000,55750.00000,55275.00000,55730.00000,6387
20090115,104000,55725.00000,55760.00000,55500.00000,55500.00000,6454
20090115,104500,55500.00000,55845.00000,55470.00000,55665.00000,3748
20090115,105000,55670.00000,55760.00000,55500.00000,55535.00000,4427
20090115,105500,55535.00000,55740.00000,55500.00000,55700.00000,3572
20090115,110000,55700.00000,56105.00000,55685.00000,56105.00000,6600
20090115,110500,56120.00000,56300.00000,56105.00000,56150.00000,7304
20090115,111000,56145.00000,56200.00000,55910.00000,55950.00000,4422
20090115,111500,55940.00000,55985.00000,55770.00000,55815.00000,4347
20090115,112000,55815.00000,55890.00000,55730.00000,55790.00000,4694
20090115,112500,55750.00000,55835.00000,55640.00000,55640.00000,3574
20090115,113000,55655.00000,55680.00000,55060.00000,55060.00000,7683
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Покажем, как загрузить данные в эту программу.&lt;/p&gt;
&lt;p&gt;При первом запуске вы увидите примерно следующую картинку.&lt;/p&gt;
&lt;p&gt;&lt;img src="/file/101758/тестирование-системы-1.png/" alt="Торговые роботы тестирование систем 1" /&gt;&lt;/p&gt;
&lt;p&gt;Мы собираемся загрузить котировки, для этого нажимаем на Data Manager . &lt;strong&gt;Next -&amp;gt;  Create a new DataSet&lt;/strong&gt;.
В красном прямоугольнике выделены уже существующие DataSet. Также их видно правее в окошке DataSet. Когда мы проделаем всю операцию, новый датасет появится в этом окне.&lt;/p&gt;
&lt;p&gt;&lt;img src="/file/101759/тестирование-системы-2.png/" alt="тестирование систем 2" /&gt;&lt;/p&gt;
&lt;p&gt;После нажатия Create a new DataSet, появится окно. У нас txt файл, поэтому выбираем ASCII Files.
&lt;strong&gt;Next -&amp;gt;&lt;/strong&gt;  указываем путь к котировкам .
&lt;strong&gt;Next -&amp;gt;&lt;/strong&gt; после выбора папки в окошке появятся файлы, которые можно использовать.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Подсказка: в одной папке должны лежать файлы полностью сходные по формату. После того как мы выбрали папку, Велс обработает все файлы в этой папке. Позже, чтобы добавить какой-то новый файл у которого такие же параметры, достаточно будет просто закинуть его в папку из которой  вы загружаете историю сейчас - и Велс сразу добавит его в DataSet. Чтобы создать датасет с другим форматом, надо сохранять файл в другую папку.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="/file/101760/тестирование-системы-3.png/" alt="тестирование систем 3" /&gt;
&lt;img src="/file/101761/тестирование-системы-4.png/" alt="тестирование систем 4" /&gt;
&lt;img src="/file/101762/тестирование-системы-5.png/" alt="тестирование систем 5" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Next -&amp;gt;&lt;/strong&gt; выбираем интервал, который мы выбрали при загрузке.  У нас это 5 минут. Если у вас файл с 5 минутами, то из него можно создавать файлы старшего ТФ, но не наоборот. Создавать файлы старшего ТФ из младших тоже не советуется, т.к. Велс криво склеивает. Лучше отдельно загрузить старший ТФ.&lt;br /&gt;
&lt;strong&gt;Next -&amp;gt;&lt;/strong&gt; появится окно, где нам надо прописать формат для программы. В нашем случае нам надо добавить 1 -  Add Field в список Field Order. Наш формат &amp;lt;DATE&amp;gt;,&amp;lt;TIME&amp;gt;,&amp;lt;OPEN&amp;gt;,&amp;lt;HIGH&amp;gt;,&amp;lt;LOW&amp;gt;,&amp;lt;CLOSE&amp;gt;,&amp;lt;VOL&amp;gt;.  У нас не хватает Time. Выбираем его и двигаем с помощью кнопки 2 , все наименования в формате должны быть по порядку. В окошке 3, выбираем нужный нам формат. У нас  ГГГГММДД, формат времени  ЧЧММСС.
&lt;img src="/file/101768/тестирование-системы-6.png/" alt="торговые роботы, тестирование торговой системы 6" /&gt;
&lt;img src="/file/101769/тестирование-системы-7.png/" alt="торговые роботы, тестирование торговой системы 7" /&gt;
В соответствующих окошках выбираем yyyyMMdd и Hmmss. Обращаю ваше внимание, формат можно выбрать из выпадающего окна, а можно напечатать самому. Нижние три окна у нас в нужном формате.  Осталось поправить только в  Ignore Firs Lines in File поставить 1.&lt;br /&gt;
На этом процедура создания DataSet завершена.&lt;/p&gt;
&lt;p&gt;Для того, чтобы написанная на коде стратегия работала корректно, необходимо занести информацию об инструменте в Велс. Для этого заходим в &lt;strong&gt;Tools -&amp;gt; Sumbol info Manager&lt;/strong&gt;, появится окошко. Сюда необходимо заносить данные для всех новых DataSet. Тип, устанавливаем Фьючерс (или акции, елси вы будете тестировать их). Маржа -  сейчас среднее значение 9000 (минус в том, что маржа считается постоянной, и при 50 000 по РТС и при 100 000, при этом мы понимаем, что фактически она меняется). Point Value для фьючерсов 0,6. Тик равен 5 в нашем случае. Decimilars (знаков после запятой ) у нас 0 . В Symbol нужно написать точно такое же название как в DataSet.
После того как мы прописали информацию, Велс будет знать как именно расчитавать профиты и лоси для системы.
&lt;img src="/file/101770/тестирование-системы-8.png/" alt="тестирование торговой системы 8" /&gt;&lt;/p&gt;
&lt;p&gt;Осталось задать проскальзывание. &lt;strong&gt;Tools -&amp;gt; Preferences -&amp;gt; Slippage&lt;/strong&gt;. Ставим галочку для первого случая и ставим нужное нам проскальзывание. For Futures - &amp;gt; 10, проскальзывание в тиках = 50п.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ТЕСТИРОВАНИЕ ТОРГОВОЙ СТРАТЕГИИ. ПРИМЕР&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;К этому моменту у нас всё готово для тестирования стратегии.  Но самой торговой системы у нас нет. Откуда же брать идеи для создания торговых систем?  Лучший способ для начинающего системщика – взять за основу чужую торговую систему и попытаться поработать с ней. Позже, на основе ваших собственных наблюдений, вы будете создавать уникальные ТС.&lt;br /&gt;
Создание стратегии
Идея
Для создания ТС у нас должна быть идея, предположение, которое необходимо проверить. Наша идея основывается на наблюдении, что на рынке бывают дни с большим диапазоном, когда цена практически с самого открытия идет в одном направлении и закрывается  рядом с максимальной точкой.  Задача торговой системы состоит в том, чтобы поймать это движение – ударный день.
Центральные условия стратегии
Станет ли день ударным мы не знаем. Мы должны найти правила, соблюдение которых позволит нам получить систему с положительным матожиданием. На данном этапе, у нас есть только примерное представление, как стратегия должна работать. Все наши предположения нам предстоит проверить.
Предположения&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Если день ударный, то мы должны войти в него с самого утра. Если нам не удалось войти до определенного времени, день скорее всего не ударный.&lt;/li&gt;
&lt;li&gt;вход в лонг осуществляется выше уровня открытия, вход в шорт осуществляется ниже открытия. Уровень открытия служит как фильтр – если мы находимся выше, вероятность расти больше чем вероятность упасть и наоборот.&lt;/li&gt;
&lt;li&gt;вход в лонг осуществляется выше средней скользящей, вход в шорт осуществляется ниже средней скользящей. Средняя скользящая (157 – МА), используется как дополнительный фактор определения тренда.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Точка входа&lt;/strong&gt;
&lt;img src="/file/101771/тестирование-системы-9.png/" alt="торговые роботы, тестирование торговой системы 9" /&gt;
Если выполняются все центральные условия для входа, нам нужно найти последнее условие, которое спустит курок, и мы войдем в позу. Для этого нам нужно формализовать точку входа. В зависимости от условий, для входа мы используем бычье или медвежье поглощение. Вход в лонг – бычье поглощение. Вход в шорт – медвежье поглощение.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Установка стопа&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Одно из наших основных предположений было о размере стопа: так как мы собираемся взять ударный день, предполагается, что движение в нашу сторону будет сильным и без существенных откатов, что даст нам возможность входить с небольшим риском. Размер стопа будет устанавливаться в процентах. Если расстояние от дальней тени до точки входа меньше чем параметр стопа, то стоп ставится за тень. Начальный размер стопа возьмём = 0,2-0,3%, что примерно равно 300 – 450п.
Выход из позиции
Еще в самом начале мы сказали, что ударный день начинается и заканчивается близко к своим максимумам. Поэтому логично будет сделать выход в конце дня, в 23.45.
Второй тип выхода – если цена движется не в нашу сторону, то мы выходим по стоп приказу.&lt;/p&gt;
&lt;p&gt;На этом описание стратегии можно закончить, необходимые начальные правила для реализации их в тестере были оговорены. Дальнейшее изменение и дополнение стратегии будет вестись по результатам тестирования.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Краткое описание стратегии&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Ловим дни с большим диапазоном.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;вход в лонг выше открытия дня, вход в шорт ниже открытия дня&lt;/li&gt;
&lt;li&gt;Цена выше/ниже 157 средней.&lt;/li&gt;
&lt;li&gt;искать точку входа до определенного времени t.&lt;/li&gt;
&lt;li&gt;вход в лонг - бычьей моделью поглощения.&lt;/li&gt;
&lt;li&gt;входа в шорт - медвежьея модель поглощения.&lt;/li&gt;
&lt;li&gt;стоп = 0,2-0,3%  от точки входа.&lt;/li&gt;
&lt;li&gt;выход в конце дня.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Графическое представление
Для удобства сделал картинку, как это всё должно выглядеть при реализации в тестере.  Наглядно показывает выполнение центральных условий, точку входа и установку стопа.&lt;/p&gt;
&lt;p&gt;&lt;img src="/file/101772/тестирование-системы-10.png/" alt="торговые роботы, тестирование торговой системы 10" /&gt;&lt;/p&gt;
&lt;p&gt;Написание кода по алгоритму&lt;/p&gt;
&lt;p&gt;Проверка кода.
Напишем код для тестирования.
Код находится в Приложении в конце статьи.
После написания кода, нужно обязательно проверить, как он работает. Проверка осуществляется вручную.&lt;br /&gt;
Как выглядит работа кода, вы можете увидеть на картинке представленной ниже.&lt;/p&gt;
&lt;p&gt;&lt;img src="/file/101773/тестирование-системы-11.png/" alt="торговые роботы, тестирование торговой системы 11" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Методы расчета размера позиции в системе&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;После того как вы убедитесь, что код работает должным образом, можно приступить к анализу полученных данных.&lt;/p&gt;
&lt;p&gt;Нас интересует результаты системы, её доходность и просадка. Чтобы увидеть нужные нам результаты, необходимо зайти во вкладку Performance. Тут нужно сказать о способах, которыми расчитаываются результаты выполнения кода. При выборе разных способов, мы будем получать разные результаты на одной стратегии. Рассмотрим вкладку – Position Size.&lt;/p&gt;
&lt;p&gt;Starting Capital – сумма с который вы будете тестировать систему.&lt;/p&gt;
&lt;p&gt;1 – первый тип расчета позиции. Размер позиции будет постоянно выполнятся исходя из суммы указаной в fixed dollar . Если у нас ГО 7500, и в fixed dollar прописано 10 000, то размер позиции всегда будет = 1 контракту.&lt;/p&gt;
&lt;p&gt;2- Размер позиции постоянно равен определенному количеству контрактов. 100 cоntracts в нашем случае было бы равносильно 750 000 в fixed dollars.&lt;/p&gt;
&lt;p&gt;Эти два метода используются для того, чтобы увидеть – как было бы если вы постоянно торговали фиксированной суммой/сайзом. Третий способ отличается от передидущих двух, для тестирования систем мы используем именно его. Percent of Equity – размер позиции расчитывается изходя из имеющейся суммы, которая меняется по ходу тестирования. Если изначально у нас было 100 000 и на 50% от депозита размер позиции равен 6 контрактам, на сумме 200 000, он будет равен 12 контрактам. Тоесть в этом методе используется реинвестирование, и мы увидим какую доходность покажет система, если постоянно вкладывать заработаные деньги в систему. Также при таком подходе мы видим, какая может быть действительная просадка у системы. Этот вопрос расмотрим поподробнее.&lt;/p&gt;
&lt;p&gt;Drawdown&lt;/p&gt;
&lt;p&gt;&lt;img src="/file/101774/тестирование-системы-12.png/" alt="торговые роботы, тестирование торговой системы 12" /&gt;&lt;/p&gt;
&lt;p&gt;Размер просадки при 1 и 2 методе расчета размера позиции в сравнение с 3 методом.&lt;/p&gt;
&lt;p&gt;Наиболее наглядно просадку системы в графическом отображении видно во вкладке Drawdown.  Просадка системы – сколько процентов мы потеряли, после максимума на счете. Впадины – отображение просадки, наибольшие впадины образовывались после последовательности убыточных сделок.
На данной картинке видно, что при использовании второго метода расчета позиции, максимальная просадка в системе была в самом начале.&lt;/p&gt;
&lt;p&gt;Картинки приведены с другой системы, не с той, что сейчас разбираем мы!&lt;/p&gt;
&lt;p&gt;&lt;img src="/file/101775/тестирование-системы-13.png/" alt="торговые роботы, тестирование торговой системы 13" /&gt;&lt;/p&gt;
&lt;p&gt;Посмотрим на эту же систему, где размер позиции рассчитывался исходя из процента размера депозита.&lt;/p&gt;
&lt;p&gt;&lt;img src="/file/101776/тестирование-системы-14.png/" alt="торговые роботы, тестирование торговой системы 14" /&gt;&lt;/p&gt;
&lt;p&gt;Сразу видно сильное различие. На обеих картинках приведена одна система. Так в чем же дело? При расчете размера позиции от депозита мы постоянно рискуем одинаковой частью депозита вне зависимости от его размера.  При первом и втором методе, если система заработала некоторую сумму, например 100 000, при начальном капитале в 100 000, итого 200 000,  и мы продолжает работать фиксированным количеством контрактов – 6 контрактов, при этом часть используемого депозита постоянно уменьшается, соответственно уменьшаются размер возможной просадки.
При первом и втором методе размер просадки сильно зависит от того, в какой момент мы начали тестировать систему. При третьем методе, мы видим, какую просадку мы могли получить, если бы вошли в рынок на протяжении всего периода тестирования, соответственно нет такого недостатка, как момент начала тестирования.&lt;/p&gt;
&lt;p&gt;Это одна из причин, почему мы используем третий метод расчета размера позиции при тестировании.
Performance
Наиболее полную информацию о результатах тестирования системы можно увидеть на вкладке Performance.
Рассмотрим некоторые строки из данной вкладки.&lt;/p&gt;
&lt;p&gt;Backtest Performance Report | Range – временные рамки, в которых проводилось тестирование.  * Сами временные рамки задаются слева в Data Range.  Data Range заданный вами может не совпадать с Range.&lt;/p&gt;
&lt;p&gt;Net profit – сколько денег заработала система с момента начала тестирования.&lt;/p&gt;
&lt;p&gt;Net profit % - сколько процентов заработала система с момента начала тестирования.&lt;/p&gt;
&lt;p&gt;Annualized Gain – Средний % годовых от стратегии. * если стратегия тестируется на промежутке меньше чем год, в данной строке пишется, сколько было бы на конец года, если стратегия продолжала работать с такой доходностью, как и в доступный тестируемый промежуток.&lt;/p&gt;
&lt;p&gt;Number of trades – количество совершенных сделок.&lt;/p&gt;
&lt;p&gt;Average Profit – средняя прибыль за одну сделку.&lt;/p&gt;
&lt;p&gt;Win/Loss Rate – процент прибыльных/убыточных сделок&lt;/p&gt;
&lt;p&gt;Average Profit/Loss – средний профит/лосс по итогам всех
прибыльных/убыточных сделок.&lt;/p&gt;
&lt;p&gt;Max consecutive Winners/Losses – максимальное количество подряд прибыльных/убыточных сделок.&lt;/p&gt;
&lt;p&gt;Maximum drawdown – максимальная просадка системы.&lt;/p&gt;
&lt;p&gt;Итак, на картинке снизу, мы видим результаты тестирования стратегии (тестирование проводилось на промежутке 2009 – 2010 год). Результаты совсем не те, на что мы рассчитывали: огромная просадка, при практически нулевом профите. В чем проблема, почему стратегия, так плохо работает, ведь были соблюдены все условия, и код проверен, работает правильно?!&lt;/p&gt;
&lt;p&gt;Результаты тестирования нас не удовлетворили.  Давайте попробуем улучшить нашу стратегию. Существует несколько способов улучшения результатов стратегии
– тестирование параметров.
– изменение условий работы стратегии.&lt;/p&gt;
&lt;p&gt;&lt;img src="/file/101777/тестирование-системы-15.png/" alt="торговые роботы, тестирование торговой системы 15" /&gt;&lt;/p&gt;
&lt;p&gt;Сначала попробуем оптимизировать параметры системы. Параметров в нашей системе 3  (5)
– МА период скользящей средней: Может так оказаться, что МА с другим периодом лучше работает.
– Время, до какого времени мы ищем сигнал: Возможно, что ждать сигнала до 2х часов излишне. Параметр время разбит отдельно для коротких и длинных позиций.
– Риск. Размер стопа после входа в позу: Стоп в нашем случае не превышает заданного параметра.
Оптимизация параметров
Важно научиться, по результатам оптимизации не  только выбирать наиболее прибыльные значения параметров, но и также находить некоторые закономерности, которые могут помочь нам улучшить стратегию.&lt;/p&gt;
&lt;p&gt;В любой системе есть параметры. Про параметры в системе следует сказать следующее:
А – параметры должны иметь под собой какое-то обоснование. Например, параметр время – работать после N часов дня, не имеет смысла, т.к. если это ударный день, то мы уже должны были войти в позицию, и нас не должно было выбить по стопу. Иначе – это не ударный день, искать входов не имеет смысла. Назначение этого параметра – найти время, до которого стоит искать признаки ударного дня, и после которого становится больше ложных сигналов.
Б – параметр можно переоптимизировать – подогнать под определенный промежуток времени, когда он будет хорошо работать, но в другое время будет работать намного хуже. Нужно избегать таких ситуаций.
В – система должна работать прибыльно на большом наборе значений параметра. Что значит - если есть параметр с 10ю различными значениями, система должна работать на  большинстве из этих значений.&lt;br /&gt;
Г – чем их меньше, тем лучше. Увеличение количества параметров делает систему менее устойчивой.&lt;/p&gt;
&lt;p&gt;Проведем оптимизацию наших параметров&lt;/p&gt;
&lt;p&gt;Для того чтобы открылась вкладка Optimization, необходимо нажать на  Optimize в левом нижнем углу.&lt;/p&gt;
&lt;p&gt;Optimization control – настройка, выбор тех параметров что мы будем тестировать. Чтобы оптимизация проходила быстрее, стоит выбирать один-два параметра и тестировать их. Чтобы удалить параметры, которые мы не хотим тестировать, выделяем его и нажимаем Remove Selected Parameter. Восстановить начальный вид можно нажав Rollback Changes. После того как мы произвели необходимые настройки, нажимаем Begin Optimization.&lt;/p&gt;
&lt;p&gt;Results – результаты тестирования в текстовом виде.&lt;/p&gt;
&lt;p&gt;1 Parameter Graph  - на шкале отображается результат тестирования только одного параметра.&lt;/p&gt;
&lt;p&gt;2 Parameter Graph – Отображаются сразу два параметра.&lt;/p&gt;
&lt;p&gt;&lt;img src="/file/101778/тестирование-системы-16.png/" alt="торговые роботы, тестирование торговой системы 16" /&gt;&lt;/p&gt;
&lt;p&gt;Быстрее и нагляднее всего тестировать пару параметров. Например, Время - Риск лонг, Время_S -   Риск шорт, Время – Время_S . Надо понимать, что если мы изменим один параметр, то он потянет за собой другой параметр. Поэтому тестировать лучше всего как раз такие пары, где один параметр влияет на другой.&lt;/p&gt;
&lt;p&gt;Небольшое лирическое отступление - Этот семинар пишется онлайн, я сейчас поэтапно делаю всё, о чем пишу. После этого места я уже успел написать 5 страниц с картинками, когда понял, что пошел по неправильному пути, начал оптимизацию с пары Время – Время_S – абсолютная глупость. После того, как прооптимизировал этот параметр, пришлось еще несколько раз к нему возвращаться, т.к. я изменил риск и параметр время опять изменился. Поэтому я написал замечание выше. Думай головой, как говорится, и сэкономишь много времени. У нас бывало так, что, не проверив, как следует, код, мы принимались его тестировать, потом оказывалось, что в коде ошибка и все результаты приходилось выкидывать, а это много времени.&lt;/p&gt;
&lt;p&gt;Я еще постараюсь сделать больше ошибок, чтобы их потом не сделали вы. А сейчас пойдем по более корректному пути.&lt;/p&gt;
&lt;p&gt;Оптимизация Время – Риск Лонг&lt;/p&gt;
&lt;p&gt;&lt;img src="/file/101779/тестирование-системы-17.png/" alt="торговые роботы, тестирование торговой системы 17" /&gt;&lt;/p&gt;
&lt;p&gt;Черными линиями отмечена область, выше которой находятся положительные параметры, ниже отрицательные. Если вы помните, я говорил, что параметр должен быть прибыльным на большем наборе значений параметра. В данном случае у нас прибыльная стратегия, если параметр от 10 часов до 14 часов. Обратите внимание, -  работа до 11 часов, находится в отрицательной зоне, но не потому, что стратегия сливает, если так работать, а потому что у нас сейчас плохо работают продажи. И если работать до 11 часов по покупкам, стратегия не выходит суммарно в плюс.&lt;/p&gt;
&lt;p&gt;Если отключить в стратегии продажи, то картинка изменится именно таким образом – работа до 14 часов находится в положительной зоне при всех значениях риска.&lt;/p&gt;
&lt;p&gt;&lt;img src="/file/101780/тестирование-системы-18.png/" alt="торговые роботы, тестирование торговой системы 18" /&gt;&lt;/p&gt;
&lt;p&gt;В стратегии УД, по нашему алгоритму, не бывает таких ситуаций, что если мы войдем в Лонг, то потом можем пропустить сигнал в шорт. Т.е. сам алгоритм, сделан таким образом, что при всех параметрах такая ситуация невозможна. Поэтому в данной стратегии можно отключить продажи, не повлияв не покупки. Я отключил продажи именно для того, чтобы вы убедились в том, что работать до 11 часов прибыльно, хотя это было ясно и по первой картинке.
&lt;img src="/file/101781/тестирование-системы-19.png/" alt="торговые роботы, тестирование торговой системы 19" /&gt;
График оптимизации с другой  стороны, чтобы лучше рассмотреть результаты по риску.
Лучший параметр для риска по покупкам – 0,8-0,9%.&lt;/p&gt;
&lt;p&gt;Какие выводы можно сделать по оптимизации Время – Риск&lt;/p&gt;
&lt;p&gt;1 – Стратегия является прибыльной, если работать до 14 часов. При этом прибыль растет до 12 часов   -  посмотреть, почему прибыль начинает падать после 12 часов.
2 – При параметре время до 14 часов, на всех значениях риска, стратегия является прибыльной. Это хорошо, параметр должен быть прибыльным на большом наборе своих значений.
3 –  Есть четкая тенденция, при увеличении параметра риска, прибыль растет – посмотреть, почему так происходит.&lt;/p&gt;
&lt;p&gt;Проводя тестирование систем, и оптимизируя параметры, старайтесь понять, почему именно стратегия начинает лучше работать при тех или иных изменениях. По результатам оптимизации выбираем значение для Времени = 12 часам, для Риска по покупкам = 0,9%.&lt;/p&gt;
&lt;p&gt;&lt;img src="/file/101782/тестирование-системы-20.png/" alt="торговые роботы, тестирование торговой системы 20" /&gt;&lt;/p&gt;
&lt;p&gt;Для того чтобы понять, что именно изменилось, при новых параметрах, посмотрим Performance.&lt;/p&gt;
&lt;p&gt;Когда мы изменили время работы с 14 часов до 12 часов, у нас уменьшилось в два раза количество сделок. При этом уменьшится количество прибыльных сделок, но оказалось лучше отказаться от половины прибыльных сделок, чтобы не получить в два раза больше лосей.&lt;/p&gt;
&lt;p&gt;Если изменить риск с 0,2% до 0,8%, то количество сделок уменьшится еще больше, при том, что количество прибыльных сделок возрастет. Почему так произошло? Если просмотреть входы в сделки руками, то можно увидеть ситуации, когда поставим маленький стоп, мы получали после этого еще много лосей и в итоге так и не ловили УД. Если бы мы поставили больший стоп, то смогли бы поймать УД и не получили бы лосей.&lt;/p&gt;
&lt;p&gt;&lt;img src="/file/101783/тестирование-системы-21.png/" alt="торговые роботы, тестирование торговой системы 21" /&gt;
Из полученных нами данных можно сделать выводы&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;вход в УД надо искать до 12 часов. После 12, пытаться войти в УД не имеет смысла.
Этот вывод совпадает с нашим предположением, что ловить ударный день надо в самом начале. Два дополнительных часа перед терминалом не дадут никаких преимуществ.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Маленький риск не всегда хорошо. Давайте подумаем, почему вход с большим риском в данном случае оказался лучше? В стратегии УД, мы ищем импульс в определенную сторону, одним из признаков импульса – сильное открытие в какую-то сторону. Возможно второй признак, когда движение в эту сторону резкое – получаются паттерны с большими рисками. И, несмотря на то, что стоп большой, именно этот большой стоп даёт нам дополнительное смещение вероятностей. Ставить же маленький стоп, на определенную величину невыгодно, после того как произошло резкое движение, стоп часто может быть выбит на откате.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;В самом начале темы про оптимизацию параметров, я сказал, что важно научиться по результатам оптимизации определять не только лучшие параметры, но также научиться видеть некоторые закономерности, которые помогут улучшить нашу систему.&lt;/p&gt;
&lt;p&gt;Посмотрим на оптимизацию со стороны времени еще раз. Видно, что основную прибыль дают сделки от 11 до 12 часов. С 10 до 11 прибыль есть, но по сравнению с периодом 11-12 часов, она незначительна. Сможем ли мы с помощью этого наблюдения улучшить стратегию для покупок еще больше?&lt;/p&gt;
&lt;p&gt;&lt;img src="/file/101784/тестирование-системы-22.png/" alt="торговые роботы, тестирование торговой системы 22" /&gt;&lt;/p&gt;
&lt;p&gt;Пропишем в коде условие, не входить до 11 часов.
Результаты нашего изменения приведены на картинке выше.
Количество убыточных сделок уменьшилось, количество прибыльных сделок тоже уменьшилось, но общий итог положительный – доходность выросла. Причины данного явления обсудим позже, посмотрим, как это проявляется на продажах.&lt;/p&gt;
&lt;p&gt;Оптимизация Время – Риск Шорт&lt;/p&gt;
&lt;p&gt;Повторяем процедуру для продаж.&lt;/p&gt;
&lt;p&gt;&lt;img src="/file/101785/тестирование-системы-23.png/" alt="торговые роботы, тестирование торговой системы 23" /&gt;&lt;/p&gt;
&lt;p&gt;Проведя анализ, сделаем выводы для шортов. На этот раз обойдемся без подробных объяснений: принцип, причины и выводы похожи на результаты работы по покупкам.&lt;/p&gt;
&lt;p&gt;В результате оптимизации я сделал следующие изменения в коде&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;время для продаж до 14 часов.&lt;/li&gt;
&lt;li&gt;время для продаж с 11 часов&lt;/li&gt;
&lt;li&gt;риск для продаж 0,7%&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Для того чтобы увидеть изменения результатов после проведения оптимизации для продаж, без влияния не него изменений проведённых по покупкам, отключим сигналы для покупок и сравним результаты до и после.
По Performance видно, что у нас опять уменьшилось количество сделок, увеличился процент прибыльных сделок. Изменения такие же, как после работы с покупками, что дает основание думать, что причина, почему стратегия улучшилась одна. То есть выводы для продаж будут схожи с покупками.&lt;/p&gt;
&lt;p&gt;&lt;img src="/file/101786/тестирование-системы-24.png/" alt="торговые роботы, тестирование торговой системы 24" /&gt;&lt;/p&gt;
&lt;p&gt;Performance после изменений: времени работы, рисков для покупок и продаж.&lt;/p&gt;
&lt;p&gt;&lt;img src="/file/101787/тестирование-системы-25.png/" alt="торговые роботы, тестирование торговой системы 25" /&gt;&lt;/p&gt;
&lt;p&gt;Перед тем как приступить к проверке последнего параметра – Фильтра по МА, хочу сделать небольшое отступление и рассказать одну особенность WealthLab по расчету прибыли и просадок в Performance отдельно по покупкам и продажам.&lt;/p&gt;
&lt;p&gt;&lt;img src="/file/101788/тестирование-системы-26.png/" alt="торговые роботы, тестирование торговой системы 26" /&gt;&lt;/p&gt;
&lt;p&gt;Откуда   -280%&lt;/p&gt;
&lt;p&gt;В WealthLab есть отдельный расчет просадок и прибыли по покупкам и продажам. Это сделано для удобства, чтобы можно было видеть, как они работают по отдельности. Есть одна тонкость, которая не является критической, но которую следует понимать.&lt;/p&gt;
&lt;p&gt;Посмотрите на картинку выше, слева, в столбце по продажам, указана просадка, как работает шорт. Справа тот же столбец, только NetProfit сильно изменился, при этом мы ничего не меняли в алгоритме для продаж, и, как видно из той же картинки, количество сделок не изменилось. Дело в том, что, несмотря на то, что статистика для покупок и продаж ведется отдельно, при работе кода и появлении сигнала на продажу, вход в позицию осуществляется объемом с учетом заработанных ранее денег. После того как мы прооптимизировали алгоритм для покупок, и результаты сильно выросли, в том месте где мы раньше входили объемом в 13 лотов (пример), мы теперь будет входить объемом 26, т.к. до этого мы успели заработать с помощью покупок. При этом просадка считается от суммы, которую заработали продажи.&lt;/p&gt;
&lt;p&gt;Оптимизация Фильтр МА&lt;/p&gt;
&lt;p&gt;&lt;img src="/file/101789/тестирование-системы-27.png/" alt="торговые роботы, тестирование торговой системы 27" /&gt;&lt;/p&gt;
&lt;p&gt;МА служит как некий индикатор тренда – если цена находится ниже средней, значит краткосрочный тренд нисходящий, наоборот – восходящий. Нам необходимо входить в позицию там, где у нас есть перевес вероятности, фильтр должен помогать нам находить этот перевес.
Число 157 объясняется количеством пятиминуток за один рабочий день (сейчас время торгов изменилось, количество 5м. тоже изменилось). Посмотрим, как работает стратегия на других параметрах.
Сейчас мы тестируем только один параметр, поэтому смотрим результаты в
1 Graph Parametr.&lt;/p&gt;
&lt;p&gt;По результатам оптимизации&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;на всех значениях параметра стратегия работает в плюс, это хорошо.&lt;/li&gt;
&lt;li&gt;параметр 157 один из лучших, 250 работает еще лучше, но незначительно.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Поставим значение параметра МА = 250.&lt;/p&gt;
&lt;p&gt;Выводы после оптимизации параметров.&lt;/p&gt;
&lt;p&gt;У нас получилось улучшить стратегию УД с помощью оптимизации параметров. Также, по графикам оптимизации мы смогли увидеть некоторые закономерности, которые помогли нам улучшить результаты системы.&lt;/p&gt;
&lt;p&gt;Начальный Алгоритм :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;вход в лонг выше открытия дня, вход в шорт ниже открытия дня&lt;/li&gt;
&lt;li&gt;Цена выше/ниже 157 средней.    +++ Параметр работает, оставляем.&lt;/li&gt;
&lt;li&gt;искать точку входа до определенного времени t.  +++ Выявили оптимальное время работы. С 11 до 12 для покупок и с 11 до 14 для продаж.&lt;/li&gt;
&lt;li&gt;Вход в лонг по бычьей модели поглощения.&lt;/li&gt;
&lt;li&gt;Вход в шорт по медвежьей модели поглощения.&lt;/li&gt;
&lt;li&gt;стоп = 0,2 – 0,3% от точки входа. --- оказалось что вход с маленьким стопом не оправдывает себя. Параметр был существенно изменен.&lt;/li&gt;
&lt;li&gt;выход в конце дня.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Интересным нововведением было – не входить в первый час торгов. Ранее мы не стали обсуждать это явление. На самом деле существует такое понятие как час дурака, это название появилось после исследования, которое показывало, что волатильностью в первый час торгов очень сильная и довольно трудно прогнозируемое. Заработать в это время можно в большей степени случайным образом, повезет/не повезет. Можете поискать в сети информацию на данную тему.&lt;/p&gt;
&lt;p&gt;Как еще улучшить стратегию?&lt;/p&gt;
&lt;p&gt;Хотя результаты стратегии стали намного лучше - 375% годовых, просадка оставляет желать лучшего – 43% это очень много. После того как мы исчерпали возможности оптимизации существующих параметров, вернемся к вкладке Chart, посмотрим как работает наша стратегия, возможно, после того как мы поработали с параметрами и можем отвлечься от них, мы увидим новые возможности для улучшения стратегии.&lt;/p&gt;
&lt;p&gt;&lt;img src="/file/101790/тестирование-системы-28.png/" alt="торговые роботы, тестирование торговой системы 28" /&gt;&lt;/p&gt;
&lt;p&gt;Во время просмотра Chart, мне попадались случаи подобные этому – когда у нас был хороший профит (в данном случае чистых 4,5%), а потом нас выбивало по стопу. Сразу возникает мысль – а что если сделать перенос в БУ после прохождения ценой некоторого расстояния? Или, что если мы будем фиксировать цель не в конце дня, а по математической цели, например, после 4% движения.&lt;/p&gt;
&lt;p&gt;Перед тем, как начать программировать идею, надо посмотреть, насколько часто бывали такие случаи, может быть это единичный случай, и тогда не стоит даже пробовать программировать идею. Есть способ гораздо более удобный для наших целей, чем просмотр графика.&lt;/p&gt;
&lt;p&gt;&lt;img src="/file/101791/тестирование-системы-29.png/" alt="торговые роботы, тестирование торговой системы 29" /&gt;&lt;/p&gt;
&lt;p&gt;Во вкладке trades, есть два столбца MAE% и MFE%.&lt;/p&gt;
&lt;p&gt;МАЕ% - означает, на сколько процентов цена уходила в сторону стопа.&lt;/p&gt;
&lt;p&gt;MFE% - означает, на сколько процентов максимально цена уходила в нужную нам сторону от точки входа.&lt;/p&gt;
&lt;p&gt;На приведенной картинке, видно, что были трейды, когда цена уходили на 4,5% , 2,3%, 3,7%, потом разворачивалась и мы получали убыток.  Если просмотреть все трейды, становится видно, что такие случаи имеют место быть, поэтому попробовать запрограммировать перенос в БУ после прохождения определенного %, стоит. Также попробуем запрограммировать выход по математической цели.&lt;/p&gt;
&lt;p&gt;Перенос стопа в БУ, после прохождения ценой N%.
Если цена проходит определенный путь от точки входа, то стоп переносится в БУ. Зададим это условие как параметр, допишем в код тестера.
Удостоверившись, что код работает правильно, протестируем новый параметр.&lt;/p&gt;
&lt;p&gt;&lt;img src="/file/101792/тестирование-системы-30.png/" alt="торговые роботы, тестирование торговой системы 30" /&gt;&lt;/p&gt;
&lt;p&gt;По результатам теста видно, что существенно никаких изменений, при переносе стопа в БУ нет.  В таких случаях лучше отказаться от параметра, т.к. больше количество параметров делает систему менее устойчивой.&lt;/p&gt;
&lt;p&gt;Закрытие позиции при достижении математической цели.
Сейчас, если мы находимся в позе, то выход осуществляется в конце дня. Попробуем выходить из позиции по достижению математической цели.
Дописываем этот параметр в код тестера, и тестируем его.&lt;/p&gt;
&lt;p&gt;&lt;img src="/file/101793/тестирование-системы-31.png/" alt="торговые роботы, тестирование торговой системы 31" /&gt;&lt;/p&gt;
&lt;p&gt;По результатам теста видно, что лучшие значения параметра это 9%, что, по сути, является максимальным значением. Если фиксировать прибыль при достижении 5-6-7%, к увеличению профита это не приведет, к уменьшению просадки тоже.&lt;/p&gt;
&lt;p&gt;Вывод по новым двум параметрам
Как вы смогли убедиться, смысла в переносе стопа в БУ и выходу по математической цели нет. Как было сказано в начале – вводимые параметры должны иметь под собой какое-то обоснование. Поиск точки входа в начале дня, для того чтобы поймать ударный день, имеет под собой обоснование. Выходить из позиции, потому что цена прошла определенный процент движения, не имеет под собой обоснования.  Цель должна рассчитываться исходя из текущих условий, также как и перенос в БУ должен производиться после событий, которые сигнализируют о возможном развороте.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Проверка правильности написания кода.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;После изменений в коде надо удостовериться, что код работает правильно.  После каждого изменения в коде, надо проверять, что код работает правильно, иначе есть большая и неприятная возможность заниматься анализированием и оптимизацией неправильно работающего кода.  Проверять можно полностью ручным методом, можно в помощь ручному методу использовать возможности WealthLab.
Например, возьмём результаты работы кода до внесения изменений по переносу стопа в БУ и после, установив в новой версии параметр переноса на значение 10%. 10% у нас за время тестируемой истории не было ни разу, поэтому результаты работы кода в обоих случаях должны быть одинаковыми.
На приведенном ниже рисунке мы видим, что все значении остались прежними, это косвенно подтверждает, что явных ошибок в измененном коде нет.
Можно посмотреть во вкладке trades MAE% и MFE%. Установив параметр (например, 2%) при всех MFE больше 2%, в колонке Profit видно, что стопило нас на уровне безубытка.&lt;/p&gt;
&lt;p&gt;Проверка кода на наличие ошибок по перфомансу.&lt;/p&gt;
&lt;p&gt;&lt;img src="/file/101794/тестирование-системы-32.png/" alt="торговые роботы, тестирование торговой системы 32" /&gt;&lt;/p&gt;
&lt;p&gt;Проверка кода на наличие ошибок по MAE – MFE.&lt;/p&gt;
&lt;p&gt;&lt;img src="/file/101795/тестирование-системы-33.png/" alt="торговые роботы, тестирование торговой системы 33" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Заключение&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Торговый робот, это всего лишь автоматизация вашей стратегии. Способ реализации робота несомненно важен, от выбора платформы зависит надежность и возможность реализовать Ваши алгоритмы. Но, идея стратегии лежит на первом месте, а тестирование идеи, как мы убедились, может дать нам очень многое.&lt;/p&gt;
&lt;p&gt;Удачи в ваших исследованиях&lt;/p&gt;
&lt;p&gt;Горбунов Алексей&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;StockSharp Торговые роботы&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Приложение: код для тестирования торговой системы&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;using System;
using System.Drawing;
using WealthLab;
using WealthLab.Indicators;
using WealthLab.Properties;
using System.Drawing;
 
namespace WealthLab.Strategies
{
	public class FirstStrategy : WealthScript
	{
		StrategyParameter paramMA;
		StrategyParameter paramTime;
		StrategyParameter paramTimeShort;
		StrategyParameter paramRisk;
		StrategyParameter paramRiskS;
		
		public FirstStrategy()
		{
			paramMA = CreateParameter(&amp;quot;MA&amp;quot;, 1, 1, 500, 10);
			paramTime = CreateParameter(&amp;quot;Время&amp;quot;, 12, 10, 19, 1);
			paramTimeShort = CreateParameter(&amp;quot;Время_S&amp;quot;, 11, 10, 19, 1);
			paramRisk = CreateParameter(&amp;quot;Риск лонг&amp;quot;, 0.2, 0.2, 1, 0.1);
			paramRiskS = CreateParameter(&amp;quot;Риск шорт&amp;quot;, 0.2, 0.2, 1, 0.1);
		}
        
		protected override void Execute()
		{		
			DataSeries ma = SMA.Series(Open, paramMA.ValueInt);
			PlotSeries (PricePane, SMA.Series(Open, paramMA.ValueInt), Color.Blue, LineStyle.Solid, 2);
			double sp = 0;
			double stop = 0;
              
			PlotStops();
			for(int bar = 1; bar &amp;lt; Bars.Count - 1; bar++)
			{
				if (Bars.IntradayBarNumber(bar) == 0)
				{
					sp = Bars.Open[bar];
				}
\
				if (IsLastPositionActive)
				{
					Position p = LastPosition;
					if (p.PositionType == PositionType.Short)
					{
						if (!CoverAtStop(bar, p, stop))
						{
							if (Bars.IsLastBarOfDay(bar))
							{
								CoverAtMarket(bar, p);
							}
						}
					}
					else //Long
					{
						if (!SellAtStop(bar, p, stop))
						{
							if (Bars.IsLastBarOfDay(bar))
							{
								SellAtMarket(bar, p);
							}
						}
					}
				}
				else
				{
					double high = Bars.High[bar];
					double low = Bars.Low[bar];

					if (!Bars.IsLastBarOfDay(bar) &amp;amp;&amp;amp; high &amp;lt; sp)						
					{
						if (Bars.Open[bar - 1] &amp;lt; Bars.Close[bar - 1] &amp;amp;&amp;amp; Bars.Open[bar - 1] &amp;gt; Bars.Close[bar] &amp;amp;&amp;amp;
							Bars.Date[bar + 1].Hour &amp;lt; paramTimeShort.ValueInt &amp;amp;&amp;amp; Close[bar] &amp;lt; ma[bar] )							
						{     
							stop = Math.Max(Bars.High[bar], Bars.High[bar - 1]);
        
							double openPrice = Bars.Open[bar + 1];
							double exitPrice = stop;
                                
							if (openPrice / exitPrice  &amp;gt; 1 - paramRiskS.Value / 100)
							{
								RiskStopLevel = stop;
								ShortAtMarket(bar + 1);
							}
							else
							{
								stop = openPrice / (1 - paramRiskS.Value / 100);
								RiskStopLevel = stop;
								ShortAtMarket(bar + 1);
							}
						}
					}

					if (!Bars.IsLastBarOfDay(bar) &amp;amp;&amp;amp; low &amp;gt; sp)
					{
						if (Bars.Open[bar - 1] &amp;gt; Bars.Close[bar - 1] &amp;amp;&amp;amp; Bars.Open[bar - 1] &amp;lt; Bars.Close[bar] &amp;amp;&amp;amp;
							Bars.Date[bar + 1].Hour &amp;lt; paramTime.ValueInt &amp;amp;&amp;amp; Close[bar] &amp;gt; ma[bar] )
						{        
							stop = Math.Min(Bars.Low[bar], Bars.Low[bar - 1]);
                                
							double openPrice = Bars.Open[bar + 1];
							double exitPrice = stop;
							
							if (exitPrice / openPrice  &amp;gt; 1 - paramRisk.Value / 100)
							{
								RiskStopLevel = stop;
								BuyAtMarket(bar + 1);
							}
							else
							{
								stop = (1 - paramRisk.Value / 100) * openPrice;
								RiskStopLevel = stop;
								BuyAtMarket(bar + 1);
							}
						}		
					}
				}
			}
		}
	}
}

&lt;/code&gt;&lt;/pre&gt;
</content>
  </entry>
  <entry>
    <id>https://stocksharp.ru/topic/360/</id>
    <title type="text">Создание роботов с помощью S#. Введение</title>
    <published>2012-03-18T21:58:29Z</published>
    <updated>2012-12-17T15:07:11Z</updated>
    <author>
      <name>FinDirector</name>
      <uri>https://stocksharp.ru/users/473/</uri>
      <email>info@stocksharp.ru</email>
    </author>
    <category term="Для начинающих" />
    <category term="Программирование роботов" />
    <category term="API" />
    <category term="Примеры" />
    <category term="Торговые роботы" />
    <category term="Статьи" />
    <content type="html">&lt;p&gt;Решил написать несколько простых статей о том, как можно разрабатывать роботов с использованием библиотеки S#.
В саму библиотеку уже входят примеры, но они достаточно простые и их нельзя использовать в реальном приложении.&lt;/p&gt;
&lt;p&gt;Предложенная архитектура робота включает следующие особенности:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Интерфейс в стиле METRO UI.&lt;/li&gt;
&lt;li&gt;Паттерн MVVM для написания интерфейса робота.&lt;/li&gt;
&lt;li&gt;Корректная обработка исключительных ситуаций.&lt;/li&gt;
&lt;li&gt;Робот позволяет запускать множество различных стратегий на разных торговых системах, разных портфелях и разных инструментах, с различными параметрами, а также позволяет задавать все эти настройки в конфигурационном XML-файле (достаточная гибкость).&lt;/li&gt;
&lt;li&gt;Хранение состояния робота.&lt;/li&gt;
&lt;li&gt;Абсолютно компактный и тривиальный код.
Приведу пример конфигурационного файла. В этом примере задается одна стратегия StrikeStrategy. Для нее задается Quik в качестве торговой системы, задается портфель, инструмент RIM2. Для получения исторических данных устанавливается провайдер, получащий данные с ФИНАМа; у него установлены свойства на получение дневных данных по инструменту RIM2. Свое состояние стратегия хранит в ветке реестра Software\FinDirector\StrikeStrategy. Размер позиции равен 20% от капитала в портфеле. Стратегия работает на 5-минутках.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class="language-xml"&gt;&amp;lt;FinDirector:StrategyLoader
 xmlns=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&amp;quot;
 xmlns:FinDirector=&amp;quot;clr-namespace:FinDirector;assembly=FinDirector&amp;quot;
 xmlns:x=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml&amp;quot;
 xmlns:System=&amp;quot;clr-namespace:System;assembly=mscorlib&amp;quot;
 xmlns:Implementation=&amp;quot;clr-namespace:FinDirector.Algo.Implementation;assembly=FinDirector.Algo&amp;quot;
 xmlns:Strategies=&amp;quot;clr-namespace:FinDirector.Algo.Strategies;assembly=FinDirector.Algo&amp;quot;&amp;gt;

 &amp;lt;FinDirector:StrategyLoader.Resources&amp;gt;
   &amp;lt;Implementation:QuikTraderBuilder x:Key=&amp;quot;MyQuik&amp;quot; Title=&amp;quot;Мой Quik&amp;quot;
     Path=&amp;quot;***&amp;quot; Login=&amp;quot;***&amp;quot; Password=&amp;quot;***&amp;quot; /&amp;gt;
   &amp;lt;Implementation:PortfolioSelector x:Key=&amp;quot;MyFortsPortfolio&amp;quot; Title=&amp;quot;Пенсионный фонд кота Мурзика&amp;quot;
     PortfolioName=&amp;quot;***&amp;quot; /&amp;gt;

   &amp;lt;!--RIM2 FinamSecurityCode--&amp;gt;
   &amp;lt;System:Int32 x:Key=&amp;quot;FinamRTSCode&amp;quot;&amp;gt;80996&amp;lt;/System:Int32&amp;gt;
   &amp;lt;Implementation:SecuritySelector x:Key=&amp;quot;fRTS&amp;quot;
     SecurityCode=&amp;quot;RIM2&amp;quot; /&amp;gt;
   &amp;lt;Implementation:SecuritySelector x:Key=&amp;quot;Si&amp;quot;
     SecurityCode=&amp;quot;SiM2&amp;quot; /&amp;gt;
 &amp;lt;/FinDirector:StrategyLoader.Resources&amp;gt;

 &amp;lt;FinDirector:StrategyLoader.Strategies&amp;gt;

   &amp;lt;Strategies:StrikeStrategy
     TraderBuilder=&amp;quot;{StaticResource MyQuik}&amp;quot;
     PortfolioSelector=&amp;quot;{StaticResource MyFortsPortfolio}&amp;quot;
     SecuritySelector=&amp;quot;{StaticResource fRTS}&amp;quot;
     TimeFrame=&amp;quot;0:5:0&amp;quot;&amp;gt;
     &amp;lt;Strategies:StrikeStrategy.HistoryCandleProvider&amp;gt;
       &amp;lt;Implementation:FinamHistoryCandleProvider TimeFrame=&amp;quot;1.0:0:0&amp;quot; FinamSecurityCode=&amp;quot;{StaticResource FinamRTSCode}&amp;quot; /&amp;gt;
     &amp;lt;/Strategies:StrikeStrategy.HistoryCandleProvider&amp;gt;
     &amp;lt;Strategies:StrikeStrategy.SettingsProvider&amp;gt;
       &amp;lt;Implementation:RegistrySettingsProvider SubKey = &amp;quot;Software\FinDirector\StrikeStrategy&amp;quot; /&amp;gt;
     &amp;lt;/Strategies:StrikeStrategy.SettingsProvider&amp;gt;
     &amp;lt;Strategies:StrikeStrategy.VolumeSizer&amp;gt;
       &amp;lt;Implementation:MarginVolumeSizer Ratio=&amp;quot;0.2&amp;quot; /&amp;gt;
     &amp;lt;/Strategies:StrikeStrategy.VolumeSizer&amp;gt;
   &amp;lt;/Strategies:StrikeStrategy&amp;gt;

 &amp;lt;/FinDirector:StrategyLoader.Strategies&amp;gt;

&amp;lt;/FinDirector:StrategyLoader&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;:[:::right
&lt;strong&gt;Автор статьи — Вадим Чижов&lt;/strong&gt;&lt;/p&gt;
&lt;div class="]"&gt;&lt;/div&gt;</content>
  </entry>
  <entry>
    <id>https://stocksharp.ru/topic/359/</id>
    <title type="text">Создание роботов с помощью S#. Часть 1. Обработка исключений</title>
    <published>2012-03-18T21:58:32Z</published>
    <updated>2012-12-17T15:07:06Z</updated>
    <author>
      <name>FinDirector</name>
      <uri>https://stocksharp.ru/users/473/</uri>
      <email>info@stocksharp.ru</email>
    </author>
    <category term="Для начинающих" />
    <category term="Программирование роботов" />
    <category term="API" />
    <category term="Примеры" />
    <category term="Торговые роботы" />
    <category term="Статьи" />
    <content type="html">&lt;p&gt;Самое главное в роботе — это обработка исключений. У нас в роботе могут быть запущено множество различных стратегий, и исключение в одном из роботов или ошибка в UI потоке не должны приводить к падению всей программы. Тем не менее именно такое поведение характерно по умолчанию для .NET программы.
Далее считаем, что наш робот является WPF – приложением! В качестве теста используем следующий код:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;		private void Window_Loaded(object sender, RoutedEventArgs e)
		{
			Task.Factory.StartNew(ThrowException);
			ThrowException();
		}

		void ThrowException()
		{
			throw new Exception(&amp;quot;ops!&amp;quot;);
		}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Вначале мы кидаем исключение в отдельном потоке (а в стратегиях события могут вызываться асинхронно), а затем в UI потоке.  Приложение упадет. Чтобы это исправить, необходимо сделать следующие правки.
В файле App.xaml.cs написать:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;		protected override void OnStartup(StartupEventArgs e)
		{
			base.OnStartup(e);

#if (DEBUG != true)
			// Don't handle the exceptions in Debug mode because otherwise the Debugger wouldn't
			// jump into the code when an exception occurs.
			DispatcherUnhandledException += AppDispatcherUnhandledException;
			AppDomain.CurrentDomain.UnhandledException += AppDomainUnhandledException;
#endif
		}

		private void AppDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
		{
			HandleException(e.Exception, false);
			e.Handled = true;
		}

		private static void AppDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
		{
			HandleException(e.ExceptionObject as Exception, e.IsTerminating);
		}

		private static void HandleException(Exception e, bool isTerminating)
		{
			if (e == null) return;

			Trace.TraceError(e.ToString());

			if (!isTerminating)
			{
				MessageBox.Show(string.Format(CultureInfo.CurrentCulture, &amp;quot;Неизвестная ошибка: {0}&amp;quot;, e.ToString()),
					&amp;quot;FinDirector&amp;quot;, MessageBoxButton.OK, MessageBoxImage.Error);
			}
		}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Тем не менее, это не спасет от крэша наше приложение при необработанных исключениях не в UI потоке. В файл app.confg необходимо добавить строки:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-xml"&gt;&amp;lt;runtime&amp;gt;
    &amp;lt;legacyUnhandledExceptionPolicy enabled=&amp;quot;1&amp;quot; /&amp;gt;
  &amp;lt;/runtime&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Теперь:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;приложение не будет падать при не критических исключениях (таких как OutOfMemory, StackOverflow);&lt;/li&gt;
&lt;li&gt;мы получим сообщение об ошибке, а не проглотим его.
:[:::right
&lt;strong&gt;Автор статьи — Вадим Чижов&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="]"&gt;&lt;/div&gt;</content>
  </entry>
  <entry>
    <id>https://stocksharp.ru/topic/358/</id>
    <title type="text">Создание роботов с помощью S#. Часть 2. Базовый класс для всех стратегий</title>
    <published>2012-03-18T21:58:41Z</published>
    <updated>2012-12-17T15:07:01Z</updated>
    <author>
      <name>FinDirector</name>
      <uri>https://stocksharp.ru/users/473/</uri>
      <email>info@stocksharp.ru</email>
    </author>
    <category term="Для начинающих" />
    <category term="Программирование роботов" />
    <category term="API" />
    <category term="Примеры" />
    <category term="Торговые роботы" />
    <category term="Статьи" />
    <content type="html">&lt;p&gt;Все наши стратегии будем наследовать от класса StandardStrategy. Зачем он нужен? Дело в том, что все стратегии часто должны уметь делать одни и теже вещи: брать откуда-то торговую систему, портфель, инструмент, исторические свечки, хранить состояние, устанавливать  размер позиции. Чтобы не решать каждый раз эти проблемы, можно сделать так:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;	public abstract class StandardStrategy : Strategy
	{
		public virtual string Description { get { return Name; } }
		public ITraderBuilder TraderBuilder { get; set; }
		public IPortfolioSelector PortfolioSelector { get; set; }
		public ISecuritySelector SecuritySelector { get; set; }
		public IVolumeSizer VolumeSizer { get; set; }
		public IHistoryCandleProvider HistoryCandleProvider { get; set; }
		public ISettingsProvider SettingsProvider { get; set; }
		public Unit PriceDelta { get; set; }

		protected StandardStrategy()
		{
			PriceDelta = 0.1.Percents();
		}
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ITraderBuilder будет  уметь волшебным образом создавать торговую систему:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;	public interface ITraderBuilder : IDisposable
	{
		string Title { get; }
		ITrader Trader { get; }
		ICandleManager CandleManager { get; }
		void RunTerminal();
		ITrader BuildTrader();
		event Action IsConnectedChanged;
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;IPortfolioSelector будет находить портфель:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;	public interface IPortfolioSelector
	{
		string Title { get; }
		Portfolio GetPortfolio(ITrader trader);
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ISecuritySelector находить инструмент:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;	public interface ISecuritySelector
	{
		string Title { get; }
		Security GetSecurity(ITrader trader);
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;IVolumeSizer расчитывать размер позиции:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;	public interface IVolumeSizer
	{
		int GetVolume(Portfolio portfolio, Security security);
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;IHistoryCandleProvider получать исторические свечки:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;	public interface IHistoryCandleProvider
	{
		List&amp;lt;TimeFrameCandle&amp;gt; GetHistoryCandles(DateTime beginDate, DateTime endDate);
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ISettingsProvider хранить состояние стратегии:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;	public interface ISettingsProvider
	{
		string ReadSetting(string name);
		void WriteSetting(string name, string value);
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Представим, что у нас уже есть реалзации всех этих интерфесов (этим мы займемся позже). Как будет выглядить конкретная стратегия?&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;	public class StrikeStrategy : StandardStrategy
	{
		public override string Description
		{
			get { return &amp;quot;Стратегия для ловли ударного дня&amp;quot;; }
		}

		CandleToken candleToken;
		DateTime strategyStartTime;

		public TimeSpan TimeFrame { get; set; }

		public StrikeStrategy()
		{
			TimeFrame = TimeSpan.FromMinutes(5);
		}

		protected override void OnStarting()
		{
			try
			{
				Trader = TraderBuilder.BuildTrader();
				if (Trader == null)
					throw new ApplicationException(string.Format(&amp;quot;Отсутствует трейдер {0}.&amp;quot;, TraderBuilder.Title));
				strategyStartTime = Trader.MarketTime;

				Portfolio = PortfolioSelector.GetPortfolio(Trader);
				if (Portfolio == null)
					throw new ApplicationException(string.Format(&amp;quot;Отсутствует портфель {0}.&amp;quot;, PortfolioSelector.Title));

				Security = SecuritySelector.GetSecurity(Trader);
				if (this.Security == null)
					throw new ApplicationException(string.Format(&amp;quot;Отсутствует инструмент {0}.&amp;quot;, SecuritySelector.Title));
				Trader.RegisterQuotes(Security);

				if (VolumeSizer != null)
				{
					Volume = VolumeSizer.GetVolume(Portfolio, Security);
					this.AddInfoLog(&amp;quot;Объем: {0}&amp;quot;, Volume);
				}

				if (TraderBuilder.CandleManager.IsTimeFrameCandlesRegistered(Security, TimeFrame))
				{
					candleToken = TraderBuilder.CandleManager.GetToken(typeof(TimeFrameCandle), Security, TimeFrame);
				}
				else
				{
					candleToken = TraderBuilder.CandleManager.RegisterTimeFrameCandles(Security, TimeFrame);
				}

				this.When(candleToken.CandlesFinished())
					.Do&amp;lt;IEnumerable&amp;lt;Candle&amp;gt;&amp;gt;(OnCandlesFinished);
			}
			catch (ApplicationException ex)
			{
				this.AddErrorLog(ex.Message);
			}

			base.OnStarting();
		}

		void OnCandlesFinished(IEnumerable&amp;lt;Candle&amp;gt; newCandles)
		{
			foreach (Candle candle in newCandles)
			{
				OnCandleFinished(candle);
			}
		}

		void OnCandleFinished(Candle candle)
		{
			DateTime currentDate = candle.Time;

			if (candle.Time &amp;lt; strategyStartTime)
				return;

			...
		}
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;:[:::right
&lt;strong&gt;Автор статьи — Вадим Чижов&lt;/strong&gt;&lt;/p&gt;
&lt;div class="]"&gt;&lt;/div&gt;</content>
  </entry>
  <entry>
    <id>https://stocksharp.ru/topic/357/</id>
    <title type="text">Создание роботов с помощью S#. Часть 3. Реализация интерфейсов</title>
    <published>2012-03-18T21:58:56Z</published>
    <updated>2012-12-17T15:06:55Z</updated>
    <author>
      <name>FinDirector</name>
      <uri>https://stocksharp.ru/users/473/</uri>
      <email>info@stocksharp.ru</email>
    </author>
    <category term="Для начинающих" />
    <category term="Программирование роботов" />
    <category term="API" />
    <category term="Примеры" />
    <category term="Торговые роботы" />
    <category term="Статьи" />
    <content type="html">&lt;p&gt;Теперь приступим к реализации интерфейсов из 2 части статьи “Создание роботов с помощью S#. Часть 2. Базовый класс для всех стратегий”. Здесь западные специалисты рекомендуют вначале реализовывать тестовые версии интерфейсов. И писать сразу UNIT-тесты. Смотрите пример SampleEmulationTesting из библиотеки S#. Но ведь программист — это высшая форма существования разума во Вселенной, и поэтому, в принципе не может ошибаться. Сразу в бой!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;QuikTraderBuilder&lt;/strong&gt;
Реализуем создание торговой системы Quik. Основной метод:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;public ITrader BuildTrader()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Нужно учитывать, что метод могут одновременно вызвать из разных потоков и создавать только 1 Quik.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;	public sealed class QuikTraderBuilder : ITraderBuilder, ILogSource
	{
		private object lockObject = new object();
		private Task task;
		private bool isConnected;

		public string Path { get; set; }
		public string Login { get; set; }
		public string Password { get; set; }

		public string DdeServer { get; set; }
		public string DllName { get; set; }

		private string title;
		public string Title
		{
			get { return title ?? Login; }
			set { title = value; }
		}

		public ITrader Trader { get; private set; }
		public ICandleManager CandleManager { get; private set; }
		public event Action IsConnectedChanged;

		public ITrader BuildTrader()
		{
			lock (lockObject)
			{
				if (task == null)
					task = Task.Factory.StartNew(CreateTrader);
			}
			task.Wait();
			return Trader;
		}

		private void CreateTrader()
		{
			QuikTerminal terminal = RunTerminalInternal();
			QuikTrader quikTrader;
			WriteLog(ErrorTypes.None, &amp;quot;Создаем шлюз взаимодействия с системой Quik.&amp;quot;);
			if (!string.IsNullOrEmpty(DdeServer))
			{
				if (!string.IsNullOrEmpty(DllName))
					quikTrader = new QuikTrader(terminal.DirectoryName, DdeServer, DllName);
				else
					quikTrader = new QuikTrader(terminal.DirectoryName, DdeServer);
			}
			else
			{
				quikTrader = new QuikTrader(terminal.DirectoryName);
			}
			quikTrader.SecuritiesTable.Columns.Add(DdeSecurityColumns.MarginBuy);
			quikTrader.SecuritiesTable.Columns.Add(DdeSecurityColumns.MinPrice);
			quikTrader.SecuritiesTable.Columns.Add(DdeSecurityColumns.MaxPrice);
			quikTrader.ReConnectionSettings.Interval = TimeSpan.FromSeconds(10);
			quikTrader.ReConnectionSettings.WorkingTime = Exchange.Rts.WorkingTime;

			quikTrader.Connected += () =&amp;gt;
			{
				UpdateIsConnected(null);
				if (!quikTrader.IsExportRunning)
				{
					WriteLog(ErrorTypes.None, &amp;quot;Запускаем экспорт данных.&amp;quot;);
					quikTrader.StartExport();
					Verify(quikTrader.Terminal);
				}
			};
			quikTrader.ConnectionError += ex =&amp;gt; UpdateIsConnected(ex);
			quikTrader.Disconnected += () =&amp;gt; UpdateIsConnected(null);

			Trader = quikTrader;
			CandleManager = new CandleManager(quikTrader);

			WriteLog(ErrorTypes.None, &amp;quot;Производим подключение.&amp;quot;);
			quikTrader.Connect();
		}

		private void UpdateIsConnected(Exception ex)
		{
			var trader = Trader;
			bool isConnectedNew = trader != null &amp;amp;&amp;amp; trader.IsConnected;
			if (isConnected != isConnectedNew)
			{
				isConnected = isConnectedNew;
				WriteLog(ErrorTypes.None, isConnectedNew ? &amp;quot;Соединение подключено.&amp;quot; : &amp;quot;Соединение отключено.&amp;quot;);
				RaiseIsConnectedChanged();
				if (ex != null) WriteLog(ErrorTypes.Error, ex.Message);
			}
		}

		private void RaiseIsConnectedChanged()
		{
			var handler = IsConnectedChanged;
			if (handler != null) handler();
		}

		public void RunTerminal()
		{
			RunTerminalInternal();
		}

		private QuikTerminal RunTerminalInternal()
		{
			QuikTerminal terminal = QuikTerminal.Get(Path);
			if (!terminal.IsLaunched)
				terminal.Launch();
			if (!terminal.IsConnected)
				terminal.Login(Login, Password);
			return terminal;
		}

		private void Verify(QuikTerminal terminal)
		{
			var errors = terminal.GetTableSettings();
			foreach (var error in errors)
			{
				string message = string.Format(&amp;quot;Таблица {0}. {1}&amp;quot;, error.Table.Caption, error.Error.Message);
				WriteLog(ErrorTypes.Warning, message);
			}
		}

		public void Dispose()
		{
			if (task != null)
				task.Dispose();
			if (CandleManager != null)
				CandleManager.Dispose();
			if (Trader != null)
				Trader.Dispose();
		}

		#region ILogSource
		public Ecng.Collections.INotifyList&amp;lt;ILogSource&amp;gt; Childs
		{
			get { return null; }
		}

		private Guid id = Guid.NewGuid();
		public Guid Id
		{
			get { return id; }
		}

		public event Action&amp;lt;LogMessage&amp;gt; Log;

		public string Name
		{
			get { return Title; }
		}

		public ILogSource Parent
		{
			get { return null; }
		}

		private void RaiseLog(LogMessage logMessage)
		{
			var handler = Log;
			if (handler != null)
				handler(logMessage);
		}

		private void WriteLog(ErrorTypes errorType, string message)
		{
			LogMessage logMessage = new LogMessage(this, DateTime.Now, errorType, message);
			RaiseLog(logMessage);
		}
		#endregion
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Создание других торговых систем оставим читателю в качестве домашнего задания.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;PortfolioSelector&lt;/strong&gt;
Реализуем получение портфеля по его имени. Основной момент: ждем, когда будет инициализирована сумма на счете, т.к. она нужна для определения размера позиции.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;	public class PortfolioSelector : IPortfolioSelector
	{
		private string title;
		public string Title
		{
			get { return title ?? PortfolioName; }
			set { title = value; }
		}

		public string PortfolioName { get; set; }

		public Portfolio GetPortfolio(ITrader trader)
		{
			Portfolio result = FindPortfolio(trader);
			if (result != null)
				return result;
			ManualResetEvent manualResetEvent = new ManualResetEvent(false);
			Action&amp;lt;IEnumerable&amp;lt;Portfolio&amp;gt;&amp;gt; onPortfoliosChanged = p =&amp;gt;
			{
				if (FindPortfolio(trader) != null)
					manualResetEvent.Set();
			};
			trader.NewPortfolios += onPortfoliosChanged;
			trader.PortfoliosChanged += onPortfoliosChanged;
			manualResetEvent.WaitOne(TimeSpan.FromSeconds(30));
			trader.NewPortfolios -= onPortfoliosChanged;
			trader.PortfoliosChanged -= onPortfoliosChanged;
			result = FindPortfolio(trader);
			return result;
		}

		private Portfolio FindPortfolio(ITrader trader)
		{
			return trader.Portfolios.FirstOrDefault(p =&amp;gt; p.Name == PortfolioName &amp;amp;&amp;amp; p.BeginAmount.Value != 0);
		}
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;SecuritySelector&lt;/strong&gt;
Поиск инструмента по его коду. Реализация аналогична PortfolioSelector.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;	public class SecuritySelector : ISecuritySelector
	{
		private string title;
		public string Title
		{
			get { return title ?? SecurityCode; }
			set { title = value; }
		}

		public string SecurityCode { get; set; }

		public Security GetSecurity(ITrader trader)
		{
			Security result = FindSecurity(trader);
			if (result != null)
				return result;
			ManualResetEvent manualResetEvent = new ManualResetEvent(false);
			Action&amp;lt;IEnumerable&amp;lt;Security&amp;gt;&amp;gt; onNewSecurities = s =&amp;gt;
			{
				if (FindSecurity(trader) != null)
					manualResetEvent.Set();
			};
			trader.NewSecurities += onNewSecurities;
			manualResetEvent.WaitOne(TimeSpan.FromSeconds(30));
			trader.NewSecurities -= onNewSecurities;
			result = FindSecurity(trader);
			return result;
		}

		private Security FindSecurity(ITrader trader)
		{
			return trader.Securities.FirstOrDefault(s =&amp;gt; s.Code == SecurityCode);
		}
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;MarginVolumeSizer&lt;/strong&gt;
Определение размера позиции по лимиту открытых позиций и гарантийному обеспечению.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;	public class MarginVolumeSizer : IVolumeSizer
	{
		public double Ratio { get; set; }
		public decimal MaxCapital { get; set; }

		public MarginVolumeSizer()
		{
			MaxCapital = decimal.MaxValue;
		}

		public int GetVolume(Portfolio portfolio, Security security)
		{
			decimal capital = Math.Min(portfolio.BeginAmount.Value, MaxCapital);
			int quantity = (int)(capital * (decimal)Ratio / security.MarginBuy);
			return quantity;
		}
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;RegistrySettingsProvider&lt;/strong&gt;
Чтение и запись состояния стратегии из реестра.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;	public class RegistrySettingsProvider : ISettingsProvider
	{
		public string SubKey { get; set; }

		public RegistrySettingsProvider()
		{
			SubKey = @&amp;quot;Software\FinDirector&amp;quot;;
		}

		public string ReadSetting(string name)
		{
			using (RegistryKey registryKey = Registry.CurrentUser.CreateSubKey(SubKey))
			{
				return (string)registryKey.GetValue(name);
			}
		}

		public void WriteSetting(string name, string value)
		{
			using (RegistryKey registryKey = Registry.CurrentUser.CreateSubKey(SubKey))
			{
				registryKey.SetValue(name, value);
			}
		}
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;FinamHistoryCandleProvider&lt;/strong&gt;
Получение исторических свечей с сайта финама. Реализацию не выкладываю, т.к. много кода.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;	public class FinamHistoryCandleProvider : IHistoryCandleProvider
	{
		public int FinamSecurityCode { get; set; }
		public TimeSpan TimeFrame { get; set; }

		public FinamHistoryCandleProvider()
		{
			FinamSecurityCode = 17455;
			TimeFrame = TimeSpan.FromHours(1);
		}

		public List&amp;lt;TimeFrameCandle&amp;gt; GetHistoryCandles(DateTime beginDate, DateTime endDate)
		{
			…
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;:[:::right
&lt;strong&gt;Автор статьи — Вадим Чижов&lt;/strong&gt;&lt;/p&gt;
&lt;div class="]"&gt;&lt;/div&gt;</content>
  </entry>
  <entry>
    <id>https://stocksharp.ru/topic/356/</id>
    <title type="text">Создание роботов с помощью S#. Часть 4. Использование XAML для загрузки стратегий</title>
    <published>2012-03-18T21:58:59Z</published>
    <updated>2012-12-17T15:06:48Z</updated>
    <author>
      <name>FinDirector</name>
      <uri>https://stocksharp.ru/users/473/</uri>
      <email>info@stocksharp.ru</email>
    </author>
    <category term="Для начинающих" />
    <category term="Программирование роботов" />
    <category term="API" />
    <category term="Примеры" />
    <category term="Торговые роботы" />
    <category term="Статьи" />
    <content type="html">&lt;p&gt;В реальном приложении у нас будет много стратегий со своими параметрами, которые проще всего загрузить из XAML файла.
XAML — это декларативный язык разметки. Он упрощает создание пользовательского интерфейса для нашего приложения.&lt;/p&gt;
&lt;p&gt;К настоящему моменту мы уже проделали большую работу по разделению бизнес-логики от UI и теперь можем в форме писать кода типа:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;		StandardStrategy strategy;

		StandardStrategy CreateStrategy()
		{
			var strategy = new StrikeStrategy()
			{
				TraderBuilder = new QuikTraderBuilder()
				{
					Path = &amp;quot;***&amp;quot;,
					Login = &amp;quot;***&amp;quot;,
					Password = &amp;quot;***&amp;quot;
				},
				PortfolioSelector = new PortfolioSelector()
				{
					PortfolioName = &amp;quot;***&amp;quot;
				},
				SecuritySelector = new SecuritySelector()
				{
					SecurityCode = &amp;quot;RIM2&amp;quot;
				},
				HistoryCandleProvider = new FinamHistoryCandleProvider()
				{
					TimeFrame = TimeSpan.FromHours(1),
					FinamSecurityCode = 80996
				},
				SettingsProvider = new RegistrySettingsProvider()
				{
					 SubKey = @&amp;quot;Software\FinDirector\StrikeStrategy&amp;quot;
				},
				VolumeSizer = new MarginVolumeSizer()
				{
					 Ratio = 0.2,
					 MaxCapital = 1000000
				},
				TimeFrame = TimeSpan.FromMinutes(5)
			};
			return strategy;
		}

		private void Window_Loaded(object sender, RoutedEventArgs e)
		{
			strategy = CreateStrategy();
		}

		protected override void OnClosed(EventArgs e)
		{
			base.OnClosed(e);
			if (strategy != null &amp;amp;&amp;amp; strategy.TraderBuilder != null)
				strategy.TraderBuilder.Dispose();
		}

		private void btnStart_Click(object sender, RoutedEventArgs e)
		{
			if (strategy.ProcessState == ProcessStates.Stopped)
				Task.Factory.StartNew(strategy.Start);
		}

		private void btnStop_Click(object sender, RoutedEventArgs e)
		{
			strategy.Stop();
		}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Получилось совсем немного кода. Тем не менее в реальном приложении у нас будет много стратегий и у каждой будет куча параметров. Чтобы не зашивать их в коде, проще всего загрузить их из XAML файла, таком как в примере из статьи &lt;a href="http://stocksharp.com/lesson/article.aspx?aid=4"&gt;“Создание роботов с помощью S#. Введение”&lt;/a&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;	public class StrategyLoader : FrameworkElement
	{
		public StrategyList Strategies { get; set; }

		public StrategyLoader()
		{
			Strategies = new StrategyList();
		}

		public static StrategyLoader Load(string location)
		{
			return (StrategyLoader)XamlReader.Load(new XmlTextReader(location));
		}
	}

	[Serializable]
	public class StrategyList : List&amp;lt;StandardStrategy&amp;gt; { }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Теперь изменим метод CreateStrategy нашей формы:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;		StandardStrategy CreateStrategy()
		{
			var strategy = StrategyLoader.Load(&amp;quot;Strategies.config&amp;quot;).Strategies.FirstOrDefault();
			return strategy;
		}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;А в файл Strategies.config поместим все настройки. В коде формы теперь нет ничего лишнего.&lt;/p&gt;
&lt;p&gt;:[:::right
&lt;strong&gt;Автор статьи: Вадим Чижов&lt;/strong&gt;&lt;/p&gt;
&lt;div class="]"&gt;&lt;/div&gt;</content>
  </entry>
  <entry>
    <id>https://stocksharp.ru/topic/355/</id>
    <title type="text">Создание роботов с помощью S#. Часть 5. Использование паттерна MVVM</title>
    <published>2012-03-18T21:59:03Z</published>
    <updated>2012-12-17T15:06:40Z</updated>
    <author>
      <name>FinDirector</name>
      <uri>https://stocksharp.ru/users/473/</uri>
      <email>info@stocksharp.ru</email>
    </author>
    <category term="Для начинающих" />
    <category term="Программирование роботов" />
    <category term="API" />
    <category term="Примеры" />
    <category term="Торговые роботы" />
    <category term="Статьи" />
    <content type="html">&lt;p&gt;Можно было бы уже остановиться на достигнутом. Но бородатые дяди в очках все время придумывают какие-то серебрянные пули. Видите ли, уважаемый программист не будет писать кучу кода в форме, а будет использовать паттерн MVVM (Model-View-ViewModel). Не существует какого-то единственно правильного способа реализовать этот паттерн, поэтому предлагаю самый простейший вариант.
Нам понадобится интерфейс IVIew и базовый класс для ViewModel:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;	public interface IView
	{
		object DataContext { get; set; }
	}

	public abstract class ViewModel : INotifyPropertyChanged
	{
		public IView View { get; protected set; }

		protected ViewModel() { }

		#region INotifyPropertyChanged Members

		public event PropertyChangedEventHandler PropertyChanged;

		protected void RaisePropertyChanged(string propertyName)
		{
			PropertyChangedEventHandler handler = PropertyChanged;
			if (handler == null) return;
			handler(this, new PropertyChangedEventArgs(propertyName));
		}

		#endregion
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;В нашем простом приложении будет две View и две ViewModel.
&lt;strong&gt;StrategyViewModel.cs&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;	class StrategyViewModel : ViewModel
	{
		public StandardStrategy Strategy { get; private set; }
		public DelegateCommand StartCommand { get; private set; }
		public DelegateCommand StopCommand { get; private set; }
		public DelegateCommand RunTerminalCommand { get; private set; }

		public StrategyViewModel(StandardStrategy strategy)
		{
			this.Strategy = strategy;

			this.StartCommand = new DelegateCommand(OnStartExecuted, CanStart);
			this.StopCommand = new DelegateCommand(OnStopExecuted, CanStop);
			this.RunTerminalCommand = new DelegateCommand(RunTerminal);
			this.Strategy.ProcessStateChanged += s =&amp;gt;
			{
				this.StartCommand.RaiseCanExecuteChanged();
				this.StopCommand.RaiseCanExecuteChanged();
			};

			this.View = new StrategyView();
			this.View.DataContext = this;
		}

		public bool CanStart()
		{
			return Strategy.ProcessState == ProcessStates.Stopped;
		}

		public void OnStartExecuted()
		{
			if (!CanStart())
				return;
			Task.Factory.StartNew(Strategy.Start);
		}

		public bool CanStop()
		{
			return Strategy.ProcessState == ProcessStates.Started;
		}

		public void OnStopExecuted()
		{
			if (!CanStop())
				return;
			MessageBoxResult result = MessageBox.Show(
				String.Format(&amp;quot;Вы уверены, что хотите остановить стратегию {0}?&amp;quot;, Strategy.Name),
				&amp;quot;Подтверждение&amp;quot;, MessageBoxButton.OKCancel);
			if (result == MessageBoxResult.OK)
				Strategy.Stop();
		}

		public void RunTerminal()
		{
			MessageBoxResult result = MessageBox.Show(
				String.Format(&amp;quot;Вы уверены, что хотите запустить терминал {0}?&amp;quot;, Strategy.TraderBuilder.Title),
				&amp;quot;Подтверждение&amp;quot;, MessageBoxButton.OKCancel);
			if (result == MessageBoxResult.OK)
				Strategy.TraderBuilder.RunTerminal();
		}
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;StrategyView помечаем интерфейсом IView:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;StrategyView.xaml.cs&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;	public partial class StrategyView : UserControl, IView
	{
		public StrategyView()
		{
			InitializeComponent();
		}
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;StrategyView.xaml&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-xml"&gt;    &amp;lt;UserControl.Resources&amp;gt;
        &amp;lt;Style x:Key=&amp;quot;stValue&amp;quot; TargetType=&amp;quot;FrameworkElement&amp;quot;&amp;gt;
            &amp;lt;Setter Property=&amp;quot;HorizontalAlignment&amp;quot; Value=&amp;quot;Right&amp;quot; /&amp;gt;
        &amp;lt;/Style&amp;gt;
    &amp;lt;/UserControl.Resources&amp;gt;
    &amp;lt;StackPanel Margin=&amp;quot;3&amp;quot;&amp;gt;
        &amp;lt;StackPanel Margin=&amp;quot;5&amp;quot;&amp;gt;
            &amp;lt;TextBlock Text=&amp;quot;{Binding Strategy.Name}&amp;quot; FontSize=&amp;quot;14&amp;quot; /&amp;gt;
            &amp;lt;TextBlock Text=&amp;quot;{Binding Strategy.Description}&amp;quot; FontSize=&amp;quot;9&amp;quot;  /&amp;gt;
            &amp;lt;Grid&amp;gt;
                &amp;lt;Grid.ColumnDefinitions&amp;gt;
                    &amp;lt;ColumnDefinition /&amp;gt;
                    &amp;lt;ColumnDefinition /&amp;gt;
                &amp;lt;/Grid.ColumnDefinitions&amp;gt;
                &amp;lt;Grid.RowDefinitions&amp;gt;
                    &amp;lt;RowDefinition /&amp;gt;
                    &amp;lt;RowDefinition /&amp;gt;
                    &amp;lt;RowDefinition /&amp;gt;
                    &amp;lt;RowDefinition /&amp;gt;
                    &amp;lt;RowDefinition /&amp;gt;
                    &amp;lt;RowDefinition /&amp;gt;
                &amp;lt;/Grid.RowDefinitions&amp;gt;
                &amp;lt;TextBlock Text=&amp;quot;Терминал: &amp;quot; Grid.Row=&amp;quot;0&amp;quot; Grid.Column=&amp;quot;0&amp;quot; /&amp;gt;
                &amp;lt;Button Grid.Row=&amp;quot;0&amp;quot; Grid.Column=&amp;quot;1&amp;quot;
                                        HorizontalAlignment=&amp;quot;Right&amp;quot;
                                        Content=&amp;quot;{Binding Strategy.TraderBuilder.Title}&amp;quot;
                                        Command=&amp;quot;{Binding Path=RunTerminalCommand}&amp;quot; /&amp;gt;

                &amp;lt;TextBlock Text=&amp;quot;Портфель: &amp;quot; Grid.Row=&amp;quot;1&amp;quot; Grid.Column=&amp;quot;0&amp;quot; /&amp;gt;
                &amp;lt;TextBlock Text=&amp;quot;{Binding Strategy.PortfolioSelector.Title}&amp;quot; Grid.Row=&amp;quot;1&amp;quot; Grid.Column=&amp;quot;1&amp;quot; Style=&amp;quot;{StaticResource stValue}&amp;quot;/&amp;gt;

                &amp;lt;TextBlock Text=&amp;quot;Инструмент: &amp;quot; Grid.Row=&amp;quot;2&amp;quot; Grid.Column=&amp;quot;0&amp;quot; /&amp;gt;
                &amp;lt;TextBlock Text=&amp;quot;{Binding Strategy.SecuritySelector.Title}&amp;quot; Grid.Row=&amp;quot;2&amp;quot; Grid.Column=&amp;quot;1&amp;quot; Style=&amp;quot;{StaticResource stValue}&amp;quot;/&amp;gt;

                &amp;lt;TextBlock Text=&amp;quot;Состояние: &amp;quot; Grid.Row=&amp;quot;3&amp;quot; Grid.Column=&amp;quot;0&amp;quot; /&amp;gt;
                &amp;lt;TextBlock Text=&amp;quot;{Binding Strategy.ProcessState}&amp;quot; Grid.Row=&amp;quot;3&amp;quot; Grid.Column=&amp;quot;1&amp;quot; Style=&amp;quot;{StaticResource stValue}&amp;quot;/&amp;gt;

                &amp;lt;TextBlock Text=&amp;quot;Прибыль: &amp;quot; Grid.Row=&amp;quot;4&amp;quot; Grid.Column=&amp;quot;0&amp;quot;/&amp;gt;
                &amp;lt;TextBlock Text=&amp;quot;{Binding Strategy.PnLManager.PnL}&amp;quot; Grid.Row=&amp;quot;4&amp;quot; Grid.Column=&amp;quot;1&amp;quot; Style=&amp;quot;{StaticResource stValue}&amp;quot;/&amp;gt;

                &amp;lt;TextBlock Text=&amp;quot;Позиция: &amp;quot; Grid.Row=&amp;quot;5&amp;quot; Grid.Column=&amp;quot;0&amp;quot;/&amp;gt;
                &amp;lt;TextBlock Text=&amp;quot;{Binding Strategy.PositionManager.Position}&amp;quot; Grid.Row=&amp;quot;5&amp;quot; Grid.Column=&amp;quot;1&amp;quot; Style=&amp;quot;{StaticResource stValue}&amp;quot;/&amp;gt;
            &amp;lt;/Grid&amp;gt;
            &amp;lt;StackPanel Orientation=&amp;quot;Horizontal&amp;quot; Margin=&amp;quot;0,5,0,0&amp;quot; HorizontalAlignment=&amp;quot;Center&amp;quot;&amp;gt;
                &amp;lt;Button x:Name=&amp;quot;btnStartStrategy&amp;quot; Content=&amp;quot;Старт&amp;quot; Command=&amp;quot;{Binding Path=StartCommand}&amp;quot; Margin=&amp;quot;2,0,0,0&amp;quot; /&amp;gt;
                &amp;lt;Button x:Name=&amp;quot;btnStopStrategy&amp;quot; Content=&amp;quot;Стоп&amp;quot; Command=&amp;quot;{Binding Path=StopCommand}&amp;quot; Margin=&amp;quot;2,0,0,0&amp;quot; /&amp;gt;
            &amp;lt;/StackPanel&amp;gt;
        &amp;lt;/StackPanel&amp;gt;
    &amp;lt;/StackPanel&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;MainViewModel.cs&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;	class MainViewModel : IDisposable
	{
		public ObservableCollection&amp;lt;StrategyViewModel&amp;gt; Strategies { get; private set; }
		public ILogListener LogView { get; private set; }
		private LogManager LogManager;

		public MainViewModel()
		{
			Strategies = new ObservableCollection&amp;lt;StrategyViewModel&amp;gt;();
			CreateLoggers();
		}

		private void CreateLoggers()
		{
			LogManager = new LogManager();

			LogView = new StockSharp.Xaml.Monitor();
			LogManager.Listeners.Add(LogView);

			var fileListener = new FileLogListener(
				string.Format(CultureInfo.InvariantCulture, &amp;quot;{0:yyyyMMdd}.txt&amp;quot;, DateTime.Today));
			LogManager.Listeners.Add(fileListener);

			if (!string.IsNullOrEmpty(Settings.GoogleLogin))
			{
				var smsListener = new SmsLogListener(Settings.GoogleLogin, Settings.GooglePassword);
				smsListener.Filters.Add(LogListener.AllErrorFilter);
				LogManager.Listeners.Add(smsListener);
			}
		}

		public void Dispose()
		{
			if (LogManager != null)
				LogManager.Dispose();
			if (Strategies != null)
			{
				foreach (ITraderBuilder traderBuilder in Strategies.Select(s =&amp;gt; s.Strategy.TraderBuilder).Distinct())
				{
					if (traderBuilder != null)
						traderBuilder.Dispose();
				}
			}
		}

		public void LoadStrategies()
		{
			StrategyLoader strategyLoader = StrategyLoader.Load(&amp;quot;Strategies.config&amp;quot;);
			Strategies.Clear();
			foreach (StandardStrategy strategy in strategyLoader.Strategies)
			{
				LogManager.Sources.Add(strategy);
				StrategyViewModel strategyModel = new StrategyViewModel(strategy);
				Strategies.Add(strategyModel);
			}
			foreach (ILogSource logSource in strategyLoader.Strategies
				.Select(s =&amp;gt; s.TraderBuilder).OfType&amp;lt;ILogSource&amp;gt;().Distinct())
			{
				LogManager.Sources.Add(logSource);
			}
		}
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;MainWindow.xaml.cs&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;	public partial class MainWindow : Window
	{
		private MainViewModel viewModel;

		public MainWindow()
		{
			InitializeComponent();
			this.Loaded += Window_Loaded;

			this.viewModel = new MainViewModel();
			this.DataContext = viewModel;
		}

		private void Window_Loaded(object sender, RoutedEventArgs e)
		{
			viewModel.LoadStrategies();
		}

		protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
		{
			base.OnClosing(e);
			MessageBoxResult result = MessageBox.Show(
				&amp;quot;Вы уверены, что хотите завершить работу?&amp;quot;,
				&amp;quot;Подтверждение&amp;quot;, MessageBoxButton.OKCancel);
			if (result != MessageBoxResult.OK)
				e.Cancel = true;
		}

		protected override void OnClosed(EventArgs e)
		{
			base.OnClosed(e);
			if (viewModel != null)
				viewModel.Dispose();
		}
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;MainWindow.xaml&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-xml"&gt;    &amp;lt;Grid&amp;gt;
        &amp;lt;Grid.RowDefinitions&amp;gt;
            &amp;lt;RowDefinition Height=&amp;quot;*&amp;quot;/&amp;gt;
            &amp;lt;RowDefinition Height=&amp;quot;*&amp;quot;/&amp;gt;
        &amp;lt;/Grid.RowDefinitions&amp;gt;

        &amp;lt;ScrollViewer Grid.Row=&amp;quot;0&amp;quot; VerticalScrollBarVisibility=&amp;quot;Auto&amp;quot;&amp;gt;
            &amp;lt;ItemsControl ItemsSource=&amp;quot;{Binding Path=Strategies}&amp;quot;&amp;gt;
                &amp;lt;ItemsControl.ItemsPanel&amp;gt;
                    &amp;lt;ItemsPanelTemplate&amp;gt;
                        &amp;lt;WrapPanel &amp;gt;&amp;lt;/WrapPanel&amp;gt;
                    &amp;lt;/ItemsPanelTemplate&amp;gt;
                &amp;lt;/ItemsControl.ItemsPanel&amp;gt;
                &amp;lt;ItemsControl.ItemTemplate&amp;gt;
                    &amp;lt;DataTemplate&amp;gt;
                        &amp;lt;ContentControl Content=&amp;quot;{Binding View}&amp;quot; /&amp;gt;
                    &amp;lt;/DataTemplate&amp;gt;
                &amp;lt;/ItemsControl.ItemTemplate&amp;gt;
            &amp;lt;/ItemsControl&amp;gt;
        &amp;lt;/ScrollViewer&amp;gt;

        &amp;lt;ContentControl Grid.Row=&amp;quot;1&amp;quot; Content=&amp;quot;{Binding LogView}&amp;quot; /&amp;gt;
    &amp;lt;/Grid&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Остается добавить к приложению стили и оно станет выглядеть как в статье &lt;a href="http://stocksharp.com/algo/article.aspx?aid=4"&gt;“Создание роботов с помощью S#. Введение”&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>https://stocksharp.ru/topic/344/</id>
    <title type="text">Простейшая стратегия долгосрочного инвестирования.</title>
    <published>2012-06-07T21:18:52Z</published>
    <updated>2012-12-17T15:06:18Z</updated>
    <author>
      <name>vlad1024</name>
      <uri>https://stocksharp.ru/users/768/</uri>
      <email>info@stocksharp.ru</email>
    </author>
    <category term="Программирование роботов" />
    <category term="WealthLab" />
    <category term="Торговые роботы" />
    <category term="Статьи" />
    <content type="html">&lt;p&gt;Попробуем сделать простейшую стратегию для долгосрочного инвестирования. В качестве рабочего будем использовать дневной таймфрейм. Вся суть стратегии будет заключаться в простейшей идее, что падение рынка обычно связано с более высокой волатильностью, чем в среднем. Соответственно, мы будем покупать, когда волатильность ниже среднего, и выходить из лонга, когда она повышается. В качестве меры волатильности будем использовать размах бара High - Low. Остается один вопрос: как измерить долгосрочное среднее волатильности? Можно использовать среднее (то есть скользящую среднюю, взятую за определенный период). Но так как мы имеем дело с распределением с тяжелыми хвостами, среднее будет плохой оценкой центра распределения. Поэтому будем использовать робастную оценку центра распределения - в нашем случае это будет медиана или, более точно, скользящая медиана, взятая с большим окном. Наши рассуждения напрямую транслируются в код на WealthLab:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using WealthLab;
using WealthLab.Indicators;

namespace WealthLab.Strategies
{
	public class MyStrategy : WealthScript
	{
		private StrategyParameter smaPeriod;
		public MyStrategy()
		{
			smaPeriod = CreateParameter(&amp;quot;Range Sma Period&amp;quot;, 1, 1, 50, 1);      
			
		}
		
		protected override void Execute()
		{
			DataSeries range = High - Low;
			DataSeries rangeSma = new WealthLab.Indicators.SMA(range, smaPeriod.ValueInt, &amp;quot;sma&amp;quot;);
			DataSeries signal = rangeSma -  new WealthLab.Indicators.Median(range, 200, &amp;quot;median&amp;quot;);
			
			for(int bar = 0; bar &amp;lt; Bars.Count; bar++)
			{				
				if (IsLastPositionActive)
				{
					//code your exit rules here
					if (signal[bar] &amp;gt; 0)
						SellAtMarket(bar + 1, LastPosition, &amp;quot;sell&amp;quot;);
				}
				else
				{
					//code your entry rules here
					if (signal[bar] &amp;lt; 0)
						BuyAtMarket(bar + 1, &amp;quot;buy&amp;quot;);
				}
			}
		}
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Единственный параметр - это длина скользящей средней для сглаживания текущего сигнала High-Low (полный аналог ATR). В дальнейшем мы будем его использовать, лишь чтобы сократить количество входов. Установим сначала smaPeriod = 1, то есть не будем использовать сглаживание сигнала.
Получим:&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101979/img1.png/" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="/file/101980/img2.png/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Судя по полученным параметрам бэктеста, идея содержит какое-то статистическое преимущество. Теперь попробудем уменьшить количество сигналов, увеличив период фильтрации High-Low. Сначала проверим робастность этого параметра, то есть убедимся, что параметры стратегии сохраняются на широком диапазоне значений параметра. После этого возьмем его, к примеру, равным 12. И как результат получаем:&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101981/img3.png/" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="/file/101982/img4.png/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Как видно, стратегия bye &amp;amp; hold принесла за рассматриваемый период нулевую доходность, в то время как наша простейшая система показала небольшую, не совсем стабильную, но прибыль.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>https://stocksharp.ru/topic/345/</id>
    <title type="text">Создание простого привода на S#</title>
    <published>2012-05-24T21:50:34Z</published>
    <updated>2012-12-17T15:06:13Z</updated>
    <author>
      <name>M.Kovaleva</name>
      <uri>https://stocksharp.ru/users/5979/</uri>
      <email>info@stocksharp.ru</email>
    </author>
    <category term="Для начинающих" />
    <category term="Программирование роботов" />
    <category term="API" />
    <category term="Примеры" />
    <category term="Торговые роботы" />
    <category term="Статьи" />
    <content type="html">&lt;p&gt;Бесплатная библиотека StockSharp предоставляет широкие возможности при разработке торговых роботов различной сложности. Но самое трудное для многих пользователей - сделать первые шаги при разработке своего робота. Поэтому представляем вашему вниманию статью-инструкцию по созданию простого привода для терминала QUIK с использованием S#.API.&lt;/p&gt;
&lt;p&gt;Для создания простого привода нам понадобится:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Quik;&lt;/li&gt;
&lt;li&gt;Библиотека S#;&lt;/li&gt;
&lt;li&gt;Visual Studio Express;&lt;/li&gt;
&lt;li&gt;Немного навыков программирования.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;**:::center
Подготовка рабочего места&lt;/p&gt;
&lt;div class="**"&gt;
&lt;ul&gt;
&lt;li&gt;Для тех, у кого не стоит бесплатный  Visual Studio Express С#,  &lt;a href="http://www.microsoft.com/visualstudio/en-us/products/2010-editions/visual-csharp-express" target="_blank"&gt;&lt;span style="color:darkred"&gt;скачиваем и устанавливаем&lt;/span&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Cкачиваем библиотеку с официального сайта &lt;a href="http://stocksharp.com/"&gt;StockSharp&lt;/a&gt;, либо - &lt;a href="https://www.box.com/stocksharp#/stocksharp/1/283684899" rel="nofollow" target="_blank"&gt;&lt;span style="color:darkred"&gt;по прямой ссылке на последнюю доступную версию&lt;/span&gt;&lt;/a&gt;. Разархивируем в какую-нибудь папку, чтобы не забыть потом.&lt;/li&gt;
&lt;li&gt;Устанавливаем Quik (демо-версию можно получить &lt;a href="http://quik.ru/user/client/quik/how-to-start/" rel="nofollow" target="_blank"&gt;&lt;span style="color:darkred"&gt;с официального сайта&lt;/span&gt;&lt;/a&gt;). Получаем логин, пароль, ключи, настраиваем Quik соответствующим образом.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;После установки Quik, его нужно настроить для работы со S#. Для этого нужно проделать 3 базовых шага:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1)&lt;/strong&gt;	Включить обработку внешних транзакций. &amp;quot;Торговля&amp;quot; → &amp;quot;Внешние Транзакции&amp;quot; → &amp;quot;Начать обработку&amp;quot; и поставить галочку &amp;quot;Запускать процесс обработки внешних транзацкий автоматически&amp;quot;&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101950/1.png/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;2)&lt;/strong&gt;	Далее нужно открыть соответствующий Wnd-файл с настройками: &amp;quot;Настройки&amp;quot; → &amp;quot;Загрузить настройки из файла&amp;quot; → выбрать wnd-файл по пути &amp;quot;Разахивированная папка&amp;quot;\Samples\Quik\info.wnd&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101951/2.png/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;3)&lt;/strong&gt;	Далее настраиваем счета : &amp;quot;Торговля&amp;quot; → &amp;quot;Настройка счетов&amp;quot; → добавить все счета в выбранные счета депо.&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101952/3.png/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;4)&lt;/strong&gt;	В итоге можно настроить окошки - подтянуть их, уменьшить, но &lt;em&gt;названия столбцов менять нельзя, так же как и удалять их&lt;/em&gt;. У разных брокеров (квиков) есть особенности , стоят определённые фильтры на таблицах &amp;quot;Мои сделки&amp;quot;, &amp;quot;Мои заявки&amp;quot;. Нажав правой кнопкой мышки на таблицу &amp;quot;Мои сделки&amp;quot;, выделить все. Аналогично и в таблице “Мои заявки”.&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101953/4.png/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Добавьте торгующийся на данный момент инструмент в таблицу &amp;quot;Инструменты&amp;quot;; по нему в дальнейшем мы будем отправлять заявки.&lt;/p&gt;
&lt;p&gt;**:::center
Создание торгового привода&lt;/p&gt;
&lt;div class="**"&gt;&lt;p&gt;Открываем Visual Studio.
Создаём новый проект → &amp;quot;Приложение Wpf&amp;quot;.
&lt;strong&gt;Настраиваем наш проект на работу S#:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Правой кнопкой мыши на &amp;quot;Проект&amp;quot; → &amp;quot;Свойства&amp;quot; и меняем &amp;quot;Требуемая версия NetFrameWork&amp;quot; (Net FrameWork 4 Client Profile ) на просто Net FrameWork 4(после этого меняется целевая среда разарботки).&lt;/li&gt;
&lt;li&gt;Добавляем нужные библиотеки в наш проект  &amp;quot;Ссылки&amp;quot; → &amp;quot;Добавить ссылку&amp;quot; → &amp;quot;Обзор&amp;quot;.&lt;/li&gt;
&lt;li&gt;Выбираем нужные нам библиотеки, которые лежат в &amp;quot;Разахрихированая папка&amp;quot;\References:
1)StockSharp.Quik
2)StockSharp.BusinessEntites
3)StockSharp.Algo
4)Ecng.Common
5)Ecng.ComponentModel
6)Ecng.Xaml&lt;/li&gt;
&lt;li&gt;Прописываем соответсвующие using на наши библиотеки в классе MainWindow.xaml.cs&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;using System.Windows;
using StockSharp.Quik;
using Ecng.Xaml;
using StockSharp.BusinessEntities;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Заходим в MainWindow.Xaml, создаём соответсвующие кнопки и другие элементы на форме нашего приложения, перетягивая их из панели элементов. Получаем следующую форму:&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101954/5.png/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Даем каждому элементу на нашей форме название, чтобы потом из кода обращаться к нему.
Нажимаем два раза на кнопку, чтобы создать метод, который будет вызываться по нажатию на эту кнопку (метод обработчик).&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Прописываем код под кнопку подключения.&lt;/em&gt;
Это простой код демонстрирующий подключение и выгрузку данных из Quik в асинхронном режиме. Теперь осталось дополнить код выводом информации на главную форму, то есть сделать вывод в наши выпадающие списки &amp;quot;Портфели&amp;quot; и &amp;quot;Инструменты&amp;quot;.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;//обьявляем переменную
        private QuikTrader _trader;
        /// &amp;lt;summary&amp;gt;
        /// Подключение к квику
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name=&amp;quot;sender&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;
        /// &amp;lt;param name=&amp;quot;e&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;
        private void Connect_Click(object sender, RoutedEventArgs e)
        {
            //создаём квик трейдера, передавая ему сразу место расположения нашего терминала
            _trader= new QuikTrader(QuikTerminal.GetDefaultPath());
            //подписываемся на событие подключения, как только подлючимся, сразу запустим Экспорт
            //Connect- просто подключение к потоку
            //StartExport- получение он-лайн данных из квика Инструменты,Заявки , Портфели и так далее
            _trader.Connected += () =&amp;gt; _trader.StartExport();
            // подключаем квик 
            _trader.Connect();

        }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Дописываем графический вывод на нашу форму в выпадающие списки&lt;/em&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;private void Connect_Click(object sender, RoutedEventArgs e)
        {
            //создаём квик трейдера, передавая ему сразу место расположения нашего терминала
            _trader= new QuikTrader(QuikTerminal.GetDefaultPath());
            //подписываемся на событие появление новых инструментов
            //оно сработает когда включится экспорт 
            _trader.NewSecurities += securities =&amp;gt;this.GuiAsync(()=&amp;gt;//GuiASync используется чтобы выводить графику из другого потока
                                                                    {
                                                                        //заполняем коллекцию у нашего выпадающего списка (ComboBox)
                                                                        Securitites.ItemsSource = _trader.Securities;
                                                                    });
            //подписываемся на событие появления новых портфелей
            //сработает после запуска экспорта
            _trader.NewPortfolios += portfolios =&amp;gt;this.GuiAsync(()=&amp;gt;
                                                                    {
                                                                        //заполняем коллекцию у нашего выпадающего списка (ComboBox)
                                                                        Portfolios.ItemsSource = _trader.Portfolios;
                                                                    });
            
            //подписываемся на событие подключения, как только подлючимся, сразу запустим Экспорт
            //Connect - просто подключение к потоку
            //StartExport- получение онлайн данных из квика Инструменты, Заявки, Портфели и так далее
            _trader.Connected += () =&amp;gt; _trader.StartExport();
            // подключаем квик 
            _trader.Connect();

        }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Запускаем проект (F5), нажимаем на кнопку &amp;quot;Подключиться&amp;quot; (в это  время у нас уже работает Quik, который подключен к котировкам). После этого наш робот включает эскпорт DDE в Quik и через некоторое время мы получаем заполненные выпадающие списки в нашем проекте.&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101955/6.png/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Остается дописать функционал под две оставшиеся кнопки &amp;quot;Купить&amp;quot;, &amp;quot;Снять все заявки&amp;quot;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;quot;Купить&amp;quot; - отправляем заявку (портфель и инструмент берется из выпадающих списков) по той цене, которая будет указана в нашем текстовом окне;&lt;/li&gt;
&lt;li&gt;&amp;quot;Снять все заявки&amp;quot; - снимаем все выставленные нами заявки.
&lt;em&gt;Код для отправки заявки&lt;/em&gt;:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;private void Buy_Click(object sender, RoutedEventArgs e)
        {
            //создаём ордер
            //заполняем его нужными свойствами
            // портфель и инструмент вынимаем из выпадающих списков
            //цену для отправки заявки вынимаем из тесктового окна
            var order = new Order
                            {
                                Trader = _trader,
                                Portfolio = (Portfolio)Portfolios.SelectedItem,
                                Security = (Security) Securitites.SelectedItem,
                                Volume = 1,
                                Price = decimal.Parse(PRICE.Text),
                                Direction = OrderDirections.Buy
                            };
            //регистрируем ордер
            _trader.RegisterOrder(order);
        }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Код для снятия всех заявок&lt;/em&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;private void CancelOrders_Click(object sender, RoutedEventArgs e)
        {
            //отменить все заявки
            _trader.CancelOrders();
        }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Пример работы простого привода&lt;/strong&gt;:&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101956/7.png/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;span style="font-size:18pt"&gt;&lt;strong&gt;Скачать исходники также можно&lt;/strong&gt;&lt;/span&gt;&lt;a href="http://narod.ru/disk/50962809001.c70d911eb0bd400850c3d7aad2fe05bd/StockSharpWpf.rar.html" rel="nofollow" target="_blank"&gt;&lt;span style="color:darkred"&gt;&lt;strong&gt;&lt;span style="font-size:18pt"&gt;здесь&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;**:[:::center
Видео-урок по созданию простого торгового робота с использованием библиотеки StockSharp:&lt;/p&gt;
&lt;div class="]"&gt;&lt;div style="text-align:center"&gt;&lt;iframe src="https://www.youtube.com/embed/-OqweF-ntR4" width="640" height="390" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align:right"&gt;&lt;p&gt;&lt;span style="font-size:18pt"&gt;&lt;span style="color:darkred"&gt;&lt;strong&gt;Автор статьи: Самунджян Артём&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;</content>
  </entry>
  <entry>
    <id>https://stocksharp.ru/topic/342/</id>
    <title type="text">Торговые роботы для QUIK или QPILE vs S#</title>
    <published>2012-08-27T19:43:03Z</published>
    <updated>2012-12-17T15:05:55Z</updated>
    <author>
      <name>M.Kovaleva</name>
      <uri>https://stocksharp.ru/users/5979/</uri>
      <email>info@stocksharp.ru</email>
    </author>
    <category term="API" />
    <category term="C#" />
    <category term="Торговые роботы" />
    <category term="Статьи" />
    <content type="html">&lt;p&gt;В QUIK есть встроенный язык программирования qpile, на котором можно писать торговых роботов. Трудно выделить какие-либо существенные плюсы в этом языке программирования: роботы работают медленно; если Вы сделали ошибку в алгоритме, найти её будет крайне сложно; нельзя реализовать интерфейс пользователя; возможности языка ограничены; зависания стратегии = низкая надежность. Кроме того, qpile не используется нигде кроме QUIK. К сожалению, язык программирования qpile – это первое, на что обратит внимание трейдер, решивший запрограммировать свою торговую систему, поскольку qpile находится в непосредственной близости к терминалу QUIK. Но если подойти к вопросу более ответственно и потратить своё время на выбор платформы, можно увидеть, что есть лучшие решения, превосходящие qpile по всем параметрам.&lt;/p&gt;
&lt;p&gt;Среди языков программирования, самый удобный для создания торговых роботов - C# (разработан Microsoft). C# используется в: WealthLab, StockSharp, QuantDevelop, OpenQuant. Возможности языка покрывают все потребности алготрейдера, а распространение языка предоставляет Вам свободу выбора.&lt;/p&gt;
&lt;p&gt;На языке С# написана библиотека для создания торговых роботов StockSharp. Что такое библиотека? Представьте себе, что Вам нужно написать код, который будет выставлять заявку на рынок или совершать любое другое действие. Код будет состоять из 100 строк, на написание и проверку которых уйдет N-е количество времени. Теперь представьте, что кто-то уже написал этот код и теперь Вы можете воспользоваться им, написав одну строчку.&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/102065/lib_sample.png/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Этот простой пример показывает, как мы экономим свое время на написание робота, используя библиотеку StockSharp. Если посмотреть другие примеры, мы увидим, что код в библиотеке может состоять из сотен строк, можете представить себе, сколько сил было потрачено на их написание и отладку.&lt;/p&gt;
&lt;p&gt;Итак, библиотека – это множество кодов, написанных профессиональными программистами. Библиотека StockSharp содержит коды, которые нужны для разработки торгового робота (подсоединение к терминалу, выставление заявки, индикаторы и т.д.). Таким образом, Вы экономите время на написание и отладку кода. Раньше только профессиональные программисты могли воспользоваться преимуществами языка программирования. С появлением Stock#, программирование торговых роботов стало доступнее.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;S# это:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Библиотека, независимая от торговых систем.&lt;/li&gt;
&lt;li&gt;Робот под одну торговую систему с минимальными изменениями переносится на другую (торговые роботы для Quik, SmartCOM, Plaza, AlfaDirect).&lt;/li&gt;
&lt;li&gt;Библиотека S# работает со всеми брокерами.&lt;/li&gt;
&lt;li&gt;Библиотека бесплатная.&lt;/li&gt;
&lt;/ul&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;a href="http://stocksharp.com/doc/"&gt;&lt;span style="color:green"&gt;&lt;strong&gt;Ознакомиться с документацией к библиотеке S#.&lt;/strong&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Вам также могут оказаться интересны статьи:&lt;/strong&gt;
&lt;a href="http://stocksharp.com/robot/screenshots.aspx"&gt;&lt;span style="color:green"&gt;&lt;strong&gt;Примеры работ, выполненных с использованием библиотеки StockSharp.&lt;/strong&gt;&lt;/span&gt; &lt;/a&gt;
&lt;a href="http://stocksharp.com/lesson/article/WhereToStart.aspx"&gt;&lt;span style="color:green"&gt;&lt;strong&gt;Торговые роботы. С чего начать. Общие вопросы.&lt;/strong&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;</content>
  </entry>
  <entry>
    <id>https://stocksharp.ru/topic/341/</id>
    <title type="text">Торговые роботы. С чего начать. Общие вопросы</title>
    <published>2012-08-27T19:43:05Z</published>
    <updated>2012-12-17T15:05:50Z</updated>
    <author>
      <name>M.Kovaleva</name>
      <uri>https://stocksharp.ru/users/5979/</uri>
      <email>info@stocksharp.ru</email>
    </author>
    <category term="Для начинающих" />
    <category term="Программирование роботов" />
    <category term="C#" />
    <category term="Торговые роботы" />
    <category term="Статьи" />
    <content type="html">&lt;p&gt;Перед человеком, решившим встать на путь алготрейдера, встает важный вопрос: какую площадку для тестирования и создания торгового робота выбрать? Согласитесь, будет обидно потратить несколько месяцев на освоение инструмента, после чего осознать его непригодность. В этой статье я постараюсь затронуть все основные направления в роботостроении и ответить на большинство вопросов начинающего алготрейдера.&lt;/p&gt;
&lt;p&gt;**:::center
Учить язык программирования или использовать визуальный редактор?&lt;/p&gt;
&lt;div class="**"&gt;&lt;p&gt;Во многих программах для тестирования торгового робота и, тем более, непосредственно для его написания, требуется знание языка программирования. Изучение языка программирования в наших умах – дело сложное и не скорое, поэтому в поиске более легких путей начали разрабатываться визуальные редакторы. Есть отличная статья, которая отражает всю суть визуальных редакторов. Выдержка из &lt;a href="http://stocksharp.blogspot.com/2011/02/blog-post_19.html" rel="nofollow" target="_blank"&gt;&lt;span style="color:green"&gt;&lt;strong&gt;статьи&lt;/strong&gt;&lt;/span&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;«В чем причина провальности таких решений? В направлении. Людям, которые только изучают программирование, визуальный редактор только навредит. Он дает первоначальный вау фактор, который исчезает уже ко второму дню использования. Через неделю, код будет выглядеть как на картинке. И вот тут как раз и происходит крах такого подхода. Они были призваны упростить программирование. А вместо этого, происходит усложнение. И более того, код в текстовом файле начинает занимать значительно меньше места, чем вся эта мега-диаграмма, не влезающая аж 8 мониторов. А уж как ее тестировать - у-у-у-у. Это отдельная тема мазохизма.»&lt;/em&gt;
**:::center
Выбор языка программирования&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="**"&gt;&lt;p&gt;Изучить язык программирования будет сложнее, чем освоить визуальный редактор, но если у Вас серьёзные намерения, это правильный выбор. Но языков программирования много, какой выбрать? Основные языки, на которых пишут роботов:
• &lt;span style="color:green"&gt;&lt;strong&gt;QPILE – встроенный язык в терминале QUIK&lt;/strong&gt;&lt;/span&gt;
• &lt;span style="color:green"&gt;&lt;strong&gt;VBA Excel&lt;/strong&gt;&lt;/span&gt;
• &lt;span style="color:green"&gt;&lt;strong&gt;Delphi&lt;/strong&gt;&lt;/span&gt;
• &lt;span style="color:green"&gt;&lt;strong&gt;C#&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;:[**:::center
QPILE&lt;/p&gt;
&lt;div class="**]"&gt;&lt;p&gt;Трудно выделить какие-либо существенные плюсы в этом языке программирования, другие языки существенно превосходят его по функциональности, возможностям и другим параметрам. Его широкое распространение связанно с тем, что до недавнего времени не существовало альтернативы, а также с тем, что терминалом QUIK пользуются большинство трейдеров и, соответственно, qpile на слуху. Единственный плюс, вытекающий из популярности qpile – довольно просто получить тех. поддержку на форумах. На qpile можно написать робота, тестировать торговые стратегии нельзя. Я не советую использовать этот язык.
:[**:::center&lt;/p&gt;
&lt;p&gt;VBA Excel&lt;/p&gt;
&lt;div class="**]"&gt;&lt;p&gt;В целом те же замечания, что и в qpile. Функционал чуть шире, но пользуются им небольшое количество трейдеров, а значит тех. поддержку получить сложно.&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;span style="color:green"&gt;&lt;strong&gt;Delphi&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Язык функциональный, на нем Вы сможете реализовать практически любую задачу, которая встанет перед Вами. Но абсолютно все придется писать самому, к тому же поддержки в виде форумов и других ресурсов нет или практически нет. Отсутствие тех. поддержки и необходимость писать весь код самому делает этот язык непривлекательным.&lt;/p&gt;
&lt;p&gt;:[:::center
&lt;strong&gt;C#&lt;/strong&gt;&lt;/p&gt;
&lt;div class="]"&gt;&lt;p&gt;С# (разработан Microsoft) выделяется по всем параметрам. Функциональность, простота и надежность сделали его фаворитом для большинства платформ для тестирования торговых стратегий. WealthLab, TS-Lab в качестве внутреннего языка программирования используют именно его. Возможность написания библиотек на C# существенно ускорила и облегчила написание торгового робота. Что такое библиотека? Представьте себе, что Вам нужно написать код, который будет выставлять заявку на рынок. Код будет состоять из 100 строк, на написание и отладку которых уйдет N-е количество времени. Теперь представьте, что кто-то уже написал этот код и теперь Вы можете воспользоваться им, написав одну строчку. Библиотека – это множество кодов, написанных проф. программистами. Библиотека StockSharp содержит все коды, которые нужны для разработки торгового робота. Таким образом, Вы экономите время на написание и отладку кода. Раньше каждый писал библиотеку для себя, для этого нужно иметь приличный опыт программирования. Теперь любой может использовать плюсы языка C#, не являясь проф. программистом. На нашем форуме оперативно отвечают на вопросы, Вы всегда сможете получить тех поддержку от первых лиц. Что мы имеем в итоге: выучив C# у вас нет привязки к какой-то одной платформе, язык используется повсеместно. На нем можно тестировать торговые стратегии как интрадей (WeathLab), так и HFT (StockSharp). Написание торговых роботов - можно самостоятельно писать свой код, можно воспользоваться библиотекой S#.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Рекомендуем ознакомиться:
&lt;a href="http://stocksharp.blogspot.com/2010/07/blog-post_12.html" rel="nofollow" target="_blank"&gt;Небольшая статья о выборе языка программирования.&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;**:[:::center
Создание торговых роботов условно можно разделить на два этапа:&lt;/p&gt;
&lt;div class="]"&gt;&lt;p&gt;1 — тестирование торговой системы;
2 — воплощение торговой системы в виде робота.&lt;/p&gt;
&lt;p&gt;**:::center&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Тестирование торговой стратегии&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="**"&gt;&lt;p&gt;Тестирование торговых систем призвано доказать прибыльность системы, найти её минусы и подсказать способы улучшить систему. Я выделю три основных платформы для тестирования:
&lt;strong&gt;WealthLab&lt;/strong&gt; — cтабильная, удобная в использовании платформа. Подойдет для тестирования внутридневных стратегий, среднесрочных, долгосрочных, тестирования на портфеле бумаг. WLD - oдно из лучший решений на данный момент. В WLD — нельзя тестировать HFT стратегии. Внутренний язык программирования в WLD — C#.
&lt;strong&gt;TSLab&lt;/strong&gt; — тот самый визуальный редактор, о котором мы говорили в самом начале. Алгоритм представлен в виде блок-схемы. Разработка относительно новая, поэтому имеются некоторые проблемы с тестированием и расчетами, хотя в последнее время проблем стало значительно меньше. Основной минус визуальных редакторов мы уже затрагивали. Если выбирать между TSLab и WLD, выбор очевиден.
&lt;strong&gt;StockSharp&lt;/strong&gt; – возможность тестирования HFT стратегий. В скором времени появится полноценная графическая среда (&lt;strong&gt;StockSharp Studio&lt;/strong&gt;) для тестирования всех видов систем.
Другие платформы для тестирования: Metastock, amibroker, OpenQuant.&lt;/p&gt;
&lt;p&gt;Дорогие друзья, время не стоит на месте, торговые платформы меняются и развиваются. Сегодня октябрь 2013 года и мы представляем вам новый, пересмотренный подход к выбору платформы для торговых роботов. Мы стараемся давать вам полную информацию, чтобы вы смогли сделать справедливый выбор, поэтому предоставляем вам ссылки на следующие статьи:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://rusalgo.com/article/what-to-choose" rel="nofollow" target="_blank"&gt;Какую платформу для торговых роботов выбрать: TSLab,WealthLab,StockSharp?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://rusalgo.com/article/stocksharp-yes-or-not" rel="nofollow" target="_blank"&gt;StockSharp (СтокШарп) – Торговые роботы. Стоит ли выбирать?&lt;/a&gt;
В этих статьях вы ознакомитесь с текущим положением дел.
Мы умеренно сообщаем вам об этом сейчас, когда вы уже прочитали половину статьи, с той целью, чтобы вы прочувствовали, как меняются технологии с течением времени. Но, с другой стороны, вы можете убедиться, что наш основной совет – изучать C# – остался прежним. Этот совет становится даже более актуальным, т.к. и  в TSLab API используется C#!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;**:::center
2. Воплощение торговой системы в виде робота&lt;/p&gt;
&lt;div class="**"&gt;&lt;p&gt;Торговые роботы реализуются двумя путями:
1 — тестирование стратегии на WealthLab (WLD), а реализация робота на qpile.
Минус такого подхода – надо знать два языка программирования: C# для WLD и qpile для QUIK.
2 — к программе для тестирования торговых систем приделывается коннектор.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Второй путь:&lt;/strong&gt;
Робот пишется на платформе для тестирования торговых систем и подсоединяется к торговому терминалу через коннектор. Удобство такого метода должно состоять в том, что после тестирования торговой стратегии Вы можете сразу вводить робота в эксплуатацию. Так задумывалось, но не всегда так бывает. Возникают различные сложности, природа которых лежит в том, что программы для тестирования стратегий создавались для тестирования, а не использования их в виде торговых роботов. Например, отсутствие обратной связи, когда после выставления заявки нельзя проверить её статус – была она исполнена или не дошла из-за разрыва интернета. Сами коннекторы чаще всего самописные, что делает связку &amp;quot;торговый робот/платформа&amp;quot; нестабильной. Для 6го WealthLab есть коннектор, написанный брокерской компанией Церих; коннектор платный - 50 рублей в день. Издержки, сопоставимые с платой за Интернет, и есть какая-то уверенность стабильной работы. Все же этот путь тупиковый: программа для тестирования стратегий накладывает сильные ограничения на функционал робота, поэтому вернемся к первому способу, когда реализация торгового робота осуществляется на языке программирования. В этом случае функционал робота ограничивается лишь возможностями языка программирования, а значит, почти не ограничен.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Первый путь:&lt;/strong&gt;
Совсем не обязательно знать два языка программирования, если Вы прислушались к совету и выбрали C#. Тестирование торговых систем идет на WLD, там пишется код на C#, потом этот же код с минимальными изменениями переносится в инфраструктуру робота, написанного на C# с использованием библиотеки StockSharp. Правильный выбор языка позволяет использовать нам лучшие решения. Функционал робота неограничен по сравнению с первым случаем. Есть возможность обратной связи (отслеживания состояния робота), автоматическое переподключение при разрыве и т.д.
Ниже показан &lt;strong&gt;пример интерфейса торгового робота, написанного с использованием библиотеки StockSharp&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Из этого окна осуществляется запуск и навигация по роботу. При нажатии кнопки &amp;quot;Старт&amp;quot; робот запускают все прописанные торговые терминалы, логинится и выполняет подключение к данным.&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/102067/2222.jpg/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Если нужно добавить новый терминал – заходим в настройку.&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/102068/3333.jpg/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Редактирование настроек робота без вмешательства во внутренний код.&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/102069/4444.jpg/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Робот отчитывается о своих действиях, пересчет алгоритма идет с заданной вами частотой.&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/102070/5555.png/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;strong&gt;Итог&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Знание языка программирования открывает перед нами широкие возможности. Выбор С# позволяет использовать лучшие решения и не привязываться к определенному продукту. Практически все продукты, связанные с тестированием ТС и созданием роботов, используют C#. Тестирование стратегии лучше всего делать в WealthLab. Реализовывать робота лучше всего, используя библиотеку S# - мы экономим своё время и упрощаем задачу написания торговых роботов.&lt;/p&gt;
&lt;p&gt;**:::center
Успехов на рынке!
Торговые роботы Stock#
Горбунов Алексей&lt;/p&gt;
&lt;div class="**"&gt;&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;a href="http://stocksharp.com/doc/"&gt;&lt;span style="color:green"&gt;&lt;strong&gt;Ознакомиться с документацией к библиотеке S# можно здесь.&lt;/strong&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;</content>
  </entry>
  <entry>
    <id>https://stocksharp.ru/topic/233/</id>
    <title type="text">Гидра умерла, да здравствует Гидра 2.0</title>
    <published>2012-10-22T02:06:00Z</published>
    <updated>2012-12-17T15:05:37Z</updated>
    <author>
      <name>StockSharp</name>
      <uri>https://stocksharp.ru/users/341/</uri>
      <email>info@stocksharp.ru</email>
    </author>
    <category term="Hydra" />
    <category term="Торговые роботы" />
    <content type="html">&lt;p&gt;Те, кто постоянно следят за изменениями в Гидре, сразу стали замечать происходящие изменения. Но мы не делали анонса перед большой аудиторией, потому-что хотели довести работу до логического завершения. И вот, наконец-то, мы официально объявляем о рождении Гидры 2.0 ! &lt;/p&gt;
&lt;p&gt;Появление новой версии не означает, что мы остановимся на достигнутом. Наоборот, мы ждем от Вас отзывов, новых предложений, отчетов о возможных ошибках и другой обратной связи.&lt;/p&gt;
&lt;p&gt;Старая Гидра честно выполняла все возложенные на нее задачи, но её дизайн был, что называется, не интуитивный. В какой-то момент мы поняли, что хотим помочь нашим пользователям в освоении программы, хотим сделать её более удобной и понятной. Поэтому летом 2012 года командой StockSharp было принято решение модернизировать Гидру.&lt;/p&gt;
&lt;p&gt;Первая Гидра имела одно единственно окно, в котором отображались все возможные инструменты из различных источников. Все это приводило к некоторой неразберихе в данных. Как это выглядело, вы можете увидеть на картинке ниже.&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/102137/resource2.png/" alt="гидра, программа для торговых роботов" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Одно из первых изменений коснулось оформления основного окна программы. Вместо одного окна, мы создали отдельные вкладки, каждая из которых имела название источника. Внутри вкладки отображались инструменты, которые относятся именно к этому источнику.&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/102136/Гидра-2.0.png/" alt="гидра, программа для торговых роботов 2.0" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Было сделано огромное количество мелких и средних изменений: все изменения перечислять нет смысла, но все они стали неотъемлемой частью Гидры 2.0&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Вот некоторые из изменений:&lt;/strong&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;Визуальное отображение статуса работы&lt;/li&gt;
&lt;li&gt;Упростили добавление новых инструментов в источник&lt;/li&gt;
&lt;li&gt;Упростили редактирование инструмента&lt;/li&gt;
&lt;li&gt;Добавлена возможность автостарта&lt;/li&gt;
&lt;li&gt;Убрали принудительное сворачивание в трей&lt;/li&gt;
&lt;li&gt;Загрузка нового типа данных из QUIK - изменения инструментов&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Произошли не только внешние изменения Гидры: мы доработали функциональную часть программы. Эта часть осталась незаметной пользователю, но повлияла на производительность Гидры и на её возможности.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.box.com/stocksharp/1/410723012/3582335043/1" rel="nofollow" target="_blank"&gt;Скачать последнюю сборку Гидры &lt;/a&gt;
Если у Вас возникнут вопросы по работе с программой, вы можете &lt;a href="http://stocksharp.com/hydra/"&gt;ознакомиться с нашей документацией&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>https://stocksharp.ru/topic/346/</id>
    <title type="text">Отладка стратегий WealthLab в Visual Studio</title>
    <published>2012-05-14T14:53:51Z</published>
    <updated>2012-12-17T14:51:17Z</updated>
    <author>
      <name>M.Kovaleva</name>
      <uri>https://stocksharp.ru/users/5979/</uri>
      <email>info@stocksharp.ru</email>
    </author>
    <category term="C#" />
    <category term="WealthLab" />
    <category term="Примеры" />
    <category term="Статьи" />
    <content type="html">&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Запускаем Visual Studio, переходим File — New project. Visual C# — Class library, не забываем поставить .NET Framework 2.0.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Добавляем ссылку на сборку WealthLab'a (WealthLab.dll). Add Reference — Browse — ищем папку с WLD (как правило, это c:\Program Files (x86)\Fidelity Investments\Wealth-Lab Pro 5\ ). Выбираем WealthLab.dll. Жмем OK.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101927/2.png/" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="/file/101928/3.png/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;ol start="3"&gt;
&lt;li&gt;Создаем два класса.Один ИмяКлассаScript (переименовываем Class1.cs), другой ИмяКлассаHelper (добавляем новый — правый клик по имени проекта, Add — Class). В диалоговом окне подтверждения переименования жмем ОК. Получается так:&lt;/li&gt;
&lt;/ol&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101929/4.png/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;ol start="4"&gt;
&lt;li&gt;Открываем ИмяКлассаScript. Добавляем директиву using WealthLab, наследуем класс от WealthScript, имплементим метод Execute() (можно нажать хоткей ALT-SHIFT-F10 затем ENTER). Должно получиться так:&lt;/li&gt;
&lt;/ol&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101930/5.png/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;ol start="5"&gt;
&lt;li&gt;Открываем ИмяКлассаHelper. Добавляем директиву using WealthLab, наследуем класс от StrategyHelper, имплементим все свойства (можно нажать хоткей ALT-SHIFT-F10 затем ENTER). Заполняем свойства:&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;Name — имя стратегии;&lt;/li&gt;
&lt;li&gt;Guid ID — правой кнопкой по имени проекта — свойства (последняя в списке), открывается окно свойств — вкладка Application — справа конпка «Assemble Information» — копируем GUID. Также здесь заполните свойство Description (например, укажите имя стратегии — Test Strategy.) Возвращаемся назад, вставляем скопированное;&lt;/li&gt;
&lt;li&gt;Author — автор;&lt;/li&gt;
&lt;li&gt;WealthScriptType — здесь вы должны указать тип вашей стратегии (ИмяКлассаScript).&lt;/li&gt;
&lt;li&gt;Description — описание стратегии;&lt;/li&gt;
&lt;li&gt;CreationDate — дата создания;&lt;/li&gt;
&lt;li&gt;LastModifiedDate — дата последней модификации стратегии.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Должно получиться так:&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101931/6.png/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;ol start="6"&gt;
&lt;li&gt;&lt;p&gt;Правой кнопкой по имени проекта — свойства (последняя в списке), открывается окно свойств — вкладка Build, свойство Output Path — указываем путь к папке WLD — c:\Program Files (x86)\Fidelity Investments\Wealth-Lab Pro 5\&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ИмяКлассаScript — пишем стратегию в методе Execute() — например, пересечение MA. Должно получиться так:&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101932/7.png/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;ol start="8"&gt;
&lt;li&gt;Билдуем стратегию, ставим точки останова. Запускаем WLD, затем в студии выбираем в меню Debug — Attach to Proces, находим процесс wealthlabpro.exe и аттачимся к нему, в WLD жмем File — Open Strategy, ваша стратегия должна быть в корне, со специальной иконкой:&lt;/li&gt;
&lt;/ol&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101933/8.png/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;ol start="9"&gt;
&lt;li&gt;Если график открыт, то стратегия сработает при нажатии кнопки ОК, если нет — то при открытии графика:&lt;/li&gt;
&lt;/ol&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101934/9.png/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Done. Теперь вы можете удообно отлаживать стратегии, ставить точки останова, смотреть значения переменных.
Для удобного аттача к wld'шному процессу можно использовать макрос:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;Imports System
 Imports EnvDTE
 Imports EnvDTE80
 Imports EnvDTE90
 Imports EnvDTE90a
 Imports EnvDTE100
 Imports System.Diagnostics

 ' 1. Tools &amp;gt; Macros &amp;gt; Macro IDE
 ' 2. Right Click MyMacros &amp;gt; Add &amp;gt; Add Module
 ' 3. Paste in the code below:
 ' 4. Rename the Macro file DebuggingMacros
 ' Enable the debug toolbar
 ' Click the dropdown on the far right and click «Add or Remove buttons» &amp;gt; click «Customize»
 ' Click «Add Command»
 ' Select Macro on the left panel
 ' Find the macro in the list on the right
 ' Click «ok»
 ' Click «Modify Selection» and rename the button
 ' * repeat for nunit macro

 Public Module DebuggingMacros
     Public Sub AttachToWealthlab()
         Dim WLDAgent As String = «WealthLabPro.exe»
         If Not AttachToProcess(WLDAgent) Then
             System.Windows.Forms.MessageBox.Show(«Ca
 n't find WLD-agent process»)
         End If
     End Sub

     Public Function AttachToProcess(ByVal ProcessName As String) As Boolean
         Dim Processes As EnvDTE.Processes = DTE.Debugger.LocalProcesses
         Dim Process As EnvDTE.Process
         Dim ProcessFound As Boolean = False
         For Each Process In Processes
             If (Process.Name.Substring(Process.Name.LastIndexOf(&amp;quot;\&amp;quot;) + 1) = ProcessName) Then
                 Process.Attach()
                 ProcessFound = True
             End If
         Next
         AttachToProcess = ProcessFound
     End Function
 End Module
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;:[**:::right
Автор статьи: AnCh&lt;/p&gt;
&lt;div class="**]"&gt;&lt;/div&gt;</content>
  </entry>
  <entry>
    <id>https://stocksharp.ru/topic/354/</id>
    <title type="text">Hunting high and low</title>
    <published>2012-04-01T13:29:42Z</published>
    <updated>2012-12-17T14:44:13Z</updated>
    <author>
      <name>vlad1024</name>
      <uri>https://stocksharp.ru/users/768/</uri>
      <email>info@stocksharp.ru</email>
    </author>
    <category term="Алготрейдинг" />
    <category term="Статьи" />
    <content type="html">&lt;p&gt;В статье мы предлагаем Вам ознакомиться с исследованием фондового рынка, которое, возможно, даст Вам зацепку в поисках своей стратегии.&lt;/p&gt;
&lt;p&gt;Данные фьючерс РТС за 10-11 год (всего 477 точек), время в минутах (начиная с 10:00) дневного хая и лоя.
(взаимная плотность, по x — время лоя, по y — время хая)&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101819/img1.png/" alt="взаимная плотность, по x - время лоя, по y - время хая" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Собственно, что мы видим: есть два типа дней. У одних наиболее вероятный хай в районе 11 часов, а лой - в 500 минут от 10:00 (то есть 18:20). Второй тип: наиболее вероятный лой в районе 11 часов, а хай в ~470 минут от 10:00 (то есть 17:50-18:00). Попытки войти со среднесрочным горизонтом и коротким стопом в другие промежутки времени резко увеличивает вероятность, что вы поймаете стоп.&lt;/p&gt;
&lt;p&gt;То же самое, но с разбивкой по дням недели:&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;strong&gt;Понедельник, Вторник&lt;/strong&gt;
&lt;img src="/file/101820/img2_12.png/" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Среда, Четверг&lt;/strong&gt;
&lt;img src="/file/101821/img2_34.png/" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Пятница&lt;/strong&gt;
&lt;img src="/file/101822/img2_5.png/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;</content>
  </entry>
  <entry>
    <id>https://stocksharp.ru/topic/353/</id>
    <title type="text">Неэффективные рынки. Теория Доу.</title>
    <published>2012-04-01T13:29:44Z</published>
    <updated>2012-12-17T14:43:22Z</updated>
    <author>
      <name>vlad1024</name>
      <uri>https://stocksharp.ru/users/768/</uri>
      <email>info@stocksharp.ru</email>
    </author>
    <category term="Алготрейдинг" />
    <category term="Статьи" />
    <content type="html">&lt;p&gt;Если немного «перепеть» классика, то тренд характеризуется тем, что каждый лоу выше/ниже предыдущего при аптренде/доунтренде. Попытаемся проверить, насколько эти представления актуальны.
Для этого возьмем дневки Ри за 2010-2011 год и посчитаем разницу между лоу текущего дня и предыдущего, то есть LowDelta = Low[Day] — Low[Day — 1]. Нас будет интересовать, насколько значения этого ряда автоскоррелированы; то есть при аптренде, если верить теории Доу, положительные значения LowDelta должны следовать за положительными, а отрицательные — за отрицательными. Соответственно, получим числовой ряд этих LowDelta, который выглядящий следующим образом:&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101825/img1.png/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;На первый взгляд, это — просто шум, но мы немного углубимся в его анализ. Чтобы как-то выразить соотношения по теории Доу, о которых сказано выше, математически, введем второй фактор — значение LowDelta за предыдущий день. Обозначим его LagLowDelta = Lag(LowDelta, 1) = Low[Day — 1] — Low[Day — 2]. Теперь нарисуем пары значений (LowDelta по X, LagLowDelta по Y):&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101826/img2.png/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Что мы здесь видим:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Плотность смещена в положительный квадрат (то есть LowDelta + и LagLowDelta +). То есть дней небольшого, но неотвратимого роста (когда лоу росли друг за другом), значительно больше.&lt;/li&gt;
&lt;li&gt;В отрицательном квадрате больше выбросов быстрого падения.
Теперь самый интересный вопрос, ради чего все это и затевалось — &lt;strong&gt;можно ли, смотря на приращения лоу, судить о тренде?&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Считаем:
Корреляция (LowDelta, LagLowDelta) = 0.21 = 21%, но она может завышать степень зависимости из-за выбросов. Поэтому посчитаем еще ранковую корреляцию Кендалла (она устойчива к любым выбросам) = 0.11 = 11%. Получилось значение в два раза меньше, но все равно статистически значимое.&lt;/p&gt;
&lt;p&gt;Таким образом, мы приходим к выводу, что несмотря на свою 100-летнюю историю, пусть и достаточно маргинально (11% статистического перевеса не так много для дневных данных), Теория Доу продолжает работать.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>https://stocksharp.ru/topic/352/</id>
    <title type="text">Curve fitter-ы из Сан-Франциского федерального резервного банка</title>
    <published>2012-04-01T20:26:25Z</published>
    <updated>2012-12-17T14:43:02Z</updated>
    <author>
      <name>vlad1024</name>
      <uri>https://stocksharp.ru/users/768/</uri>
      <email>info@stocksharp.ru</email>
    </author>
    <category term="Алготрейдинг" />
    <category term="клуб алготрейдеров" />
    <content type="html">&lt;p&gt;В чем суть — два товарища из Сан-Франциского ФЕДа (Zheng Liu — a research advisor in the Economic Research Department of the Federal Reserve Bank of San Francisco и Mark M. Spiegel — a vice president in the Economic Research Department of the Federal Reserve Bank of San Francisco), решили провести исследование на тему того, как влияет отношение стареющего населения на P/E. Конкретно в качестве коэффициента старения они взяли логарифм отношения группы 40–49 лет к 60–69 далее M/O.&lt;/p&gt;
&lt;p&gt;Оригинальная статья авторов Zheng Liu и Mark M. Spiegel размещена &lt;a href="http://www.frbsf.org/publications/economics/letter/2011/el2011-26.html" rel="nofollow" target="_blank"&gt;здесь&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Перевод статьи от &lt;a href="http://slon.ru/economics/eho_voyny_nakonec_dokatilos_do_birzhi-651960.xhtml" rel="nofollow" target="_blank"&gt;slon.ru&lt;/a&gt; размещен здесь.&lt;/p&gt;
&lt;p&gt;Ниже представлена оригинальная картинка из их расчета. Красным — PE, синим — этот коэффициент; слева — исторические данные, справа — предсказание модели.&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101827/img1.png/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Теперь они нам утверждают:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;«Statistical analysis confirms this correlation. In our model, we obtain a statistically and economically significant estimate of the relationship between the P/E and M/O ratios. We estimate that the M/O ratio explains about 61% of the movements in the P/E ratio during the sample period. In other words, the M/O ratio predicts long-run trends in the P/E ratio well. »&lt;/p&gt;
&lt;p&gt;«Статистический анализ подтвердил эти корреляции. В нашей модели мы получили статистические и экономически значимые оценки взаимосвязи между P/E и M/O(коэффициент старения). Мы оценили, что M/O отношения ОБЪЯСНЯЕТ БОЛЕЕ 61% ДВИЖЕНИЯ В P/E за заданныq период. Другими словами, M/O соотношение предсказывает долгосрочные тренды в P/E.»
Собственно, первая мысль, которая возникла и в дальнейшем нашла подтверждение — они опять прогуляли в институте курсы по эконометрике и посчитали корреляцию двух процессов. Чтобы подтвердить гипотезу, пришлось скачать их данные и воспроизвести коэффициенты (та же самая картинка что у них, с кружочками — P/E, без M/O):&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101828/img2.png/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Теперь, добравшись до данных, считаем статистически корректно ранковую корреляцию приращений между двумя процессами. Получаем 0.15 (15%) при уровне статистической значимости 90% (то есть вероятность, что данная взаимосвязь получилась чисто случайно составляет ~10%, но это нормально, учитывая малый размер выборки). Прямой тест на коинтеграцию неприменим, так как процессы не unit root (то есть не интегралы белого шума), хотя и близки к нему. Но можно построить линейной регрессией спред, а дальше проверить, насколько статистически значима ECM (error-correction model) репрезентация. Результат получается схожий: значимость вклада спреда в приращения P/E выходит за границы статистической значимости (70%-ая вероятность того, что результат получен чисто случайно).&lt;/p&gt;
&lt;p&gt;На рисунке ниже по горизонтали изображены приращения P/E, по вертикали — приращения M/O.&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101829/img3.png/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;В общем, не верьте глазам своим. Несмотря на то, что кажется будто взаимосвязь между ними значительная, если посчитать ее статистически корректно она будет в районе 15% при не высоком уровне статистической значимости. А товарищам из FRBSF должно быть стыдно за то, что они внесли очередной вклад в поток псевдо-экономического шлака, от которого и так уже некуда деваться.&lt;/p&gt;
&lt;p&gt;Данные и скрипты Вы можете &lt;a href="http://narod.ru/disk/44532460001.40bd889ca51a89f2243703e26f6b5758/agedata.zip.html" rel="nofollow" target="_blank"&gt;скачать здесь&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>https://stocksharp.ru/topic/351/</id>
    <title type="text">ЛЧИ, данные</title>
    <published>2012-04-01T20:26:28Z</published>
    <updated>2012-12-17T14:42:35Z</updated>
    <author>
      <name>vlad1024</name>
      <uri>https://stocksharp.ru/users/768/</uri>
      <email>info@stocksharp.ru</email>
    </author>
    <category term="WealthLab" />
    <category term="Python" />
    <category term="Статьи" />
    <content type="html">&lt;p&gt;С 2003 года проводится ежегодный всероссийский чемпионат по биржевой торговле – конкурс &amp;quot;Лучший частный инвестор&amp;quot;. Многим трейдерам интересна статистическая составляющая этого конкурса, а именно анализ работы его участников и агрегированные данные. В данной статье показан способ получения статистики по ЛЧИ на примере данных 2011 года с использованием Python.&lt;/p&gt;
&lt;p&gt;Скрипты на Питоне для выкачивания данных из статистики ЛЧИ и пост процессинга, а также данные по всем участникам за ЛЧИ 2011 &lt;a href="http://narod.ru/disk/44882504001.d7c35f3ac792adb077498439d010da2c/lchi.rar.html" rel="nofollow" target="_blank"&gt;скачать здесь&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Как использовать?&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Скачать и установить сборку питона, если он не установлен (&lt;a href="http://sourceforge.net/projects/numpy/files/NumPy/1.4.1/numpy-1.4.1-win32-superpack-python2.6.exe/download" rel="nofollow" target="_blank"&gt;ссылка 1&lt;/a&gt; и &lt;a href="http://www.python.org/ftp/python/2.6.2/python-2.6.2.msi" rel="nofollow" target="_blank"&gt;ссылка 2&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Набрать в командной строке команду &amp;quot;python&amp;quot;. Должна появиться консоль питона (если этого не произошло, необходимо прописать в PATH путь к интерпретатору).&lt;/li&gt;
&lt;li&gt;Скрипт &lt;em&gt;download.py&lt;/em&gt; скачивает данные для заданного года и участника. Пример: python download.py 2011 dr-mart&lt;/li&gt;
&lt;li&gt;Скрипт &lt;em&gt;agregate.py&lt;/em&gt; агрегирует скаченные данные (т.е. раскладывает по инструментам, фиксит вечернюю сессию в хронологическом порядке, немного склеивает сделки и считает балансовую позицию).
Пример: &lt;em&gt;python agregate.py 2011 dr-mart&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;В результате должно получиться (dr-mart_RIZ1.csv):&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class="language-python"&gt;code,direction,price,amount,time,date,balance 

RIZ1,1,122185.0,83,194936,20111005,83
RIZ1,-1,122220.0,-83,194956,20111005,0
RIZ1,-1,125610.0,-30,155054,20111006,-30
RIZ1,1,125965.0,6,174509,20111006,-24
RIZ1,1,125965.0,14,174510,20111006,-10
RIZ1,1,125965.0,1,174511,20111006,-9
RIZ1,1,126110.0,30,174515,20111006,21
RIZ1,1,126100.0,9,174616,20111006,30
RIZ1,1,125965.0,9,174645,20111006,39
RIZ1,-1,125100.0,-30,175144,20111006,9
RIZ1,1,125760.0,21,175858,20111006,30
RIZ1,1,126490.0,30,181004,20111006,60
RIZ1,-1,129025.0,-60,221820,20111006,0
RIZ1,-1,129780.0,-15,125659,20111007,-15
RIZ1,1,130630.0,15,160719,20111007,0
RIZ1,-1,131515.0,-15,175620,20111007,-15
RIZ1,-1,129180.0,-10,203153,20111007,-25
RIZ1,1,130750.0,25,232610,20111007,0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;В аттаче — агрегированные текущие данные за 2011 для всех участников.&lt;/p&gt;
&lt;p&gt;В корне архива &lt;em&gt;lchi/VisualizeStrategy.wld&lt;/em&gt; расположена стратегия для WealtLab 5, которая визуализирует агрегированные данные.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Порядок действий:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Экспортировать данные по инструменту в data sets за период ЛЧИ (например, через Ascii Files — данные от финама размещены в папке &lt;em&gt;lchi/rts_m1_lchi&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Создать новую пустую стратегию File → New → New Strategy From Code. В открывшуюся новую стратегию необходимо скопировать и заменить код из &lt;em&gt;VisualizeStrategy.wld&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Единственный параметр стратегии — это filePath; он идет первой строкой в методе Execute. В него необходимо прописать полный путь до файла, содержащего агрегированные с ЛЧИ данные по инструменту. Например, если распаковать архив lchi.rar в каталог c:/project, после чего мы хотим посмотреть торговлю dr-mart на ri, получаем следующее:
&lt;em&gt;string filePath = «c:/project/lchi/data/2011/agregate/dr-mart_RIZ1.csv»&lt;/em&gt;. Вместо &lt;em&gt;dr_mart_RIZ1.csv&lt;/em&gt; может быть любой другой файл из каталога &lt;em&gt;agregate&lt;/em&gt;. &lt;strong&gt;Все слэши в пути должны быть обратными, как в примере!&lt;/strong&gt;
В результате получим такую картинку (за 16.11.2011 dr-mart):&lt;/li&gt;
&lt;/ol&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101831/img1.png/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;На рисунке изображено следующее: минутный график инструмента, над ним индикатор черным цветом — чистая балансовая позиция, красная пунктирная линимя — ноль, зеленая — максимум чистой балансовой позиции, синяя — минимум.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>https://stocksharp.ru/topic/348/</id>
    <title type="text">Каким стереотипам о фондовом рынке стоит верить?</title>
    <published>2012-04-25T22:36:33Z</published>
    <updated>2012-12-17T14:41:37Z</updated>
    <author>
      <name>M.Kovaleva</name>
      <uri>https://stocksharp.ru/users/5979/</uri>
      <email>info@stocksharp.ru</email>
    </author>
    <category term="Для начинающих" />
    <category term="Алготрейдинг" />
    <category term="Статьи" />
    <content type="html">&lt;p&gt;Результаты работы на фондовом рынке зачастую воспринимаются как результат игры случая, а движения биржевых котировок и фондовых показателей - не поддающимися научному анализу и прогнозу. Несмотря на это необходимо и желательно находить статистические закономерности для возможного последующего прогноза. В данной статье я постараюсь рассказать о некоторых из них, опровергая устоявшиеся заблуждения.&lt;/p&gt;
&lt;p&gt;**:::center
Закономерность 1. Самая надежная и успешная стратегия поведения на рынке – стратегия «купил и держи» («bye and hold»)&lt;/p&gt;
&lt;div class="**"&gt;&lt;p&gt;Существует  мнение о постоянном росте рынка. В доказательство обычно приводят пример индекса Доу-Джонса, выросшего за 20 век примерно в 1000 раз.&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101859/002.JPG/" alt="График индекс Доу-Джонса" /&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Следовательно, чтобы успешно работать на бирже, нужно накупить акций и ждать; самое сложное – перетерпеть возможные коррекции рынка. Действительно, фондовый рынок обычно достаточно длительное время находится в фазах интенсивного роста, и чем дольше эта фаза длится, тем крепче укореняется мысль о стратегии «купил и держи», и начинает казаться, что это самый удобный и простой способ обогащения. Однако опыт показывает, что следование этой стратегии всегда заканчивается жестокой расплатой. Периодичность таких событий обычно составляет 15-20 лет – именно столько составляет срок инвестиционной памяти участников рынка. Самый сокрушительный крах был в 1929-м году, когда биржевики выбрасывались из окон гостиниц Нью-Йорка. Самый недавний – мировой кризис 2008 года. И не всегда рынок восстанавливается быстро, как, например, после краха 1987 года. Бывают и длительные рецессии по 5-10 и более лет. Восстановление прежних позиций после краха 1929 года продолжалось около 20 лет, еще примерно столько же, в 60-80-е годы, рынок простоял на месте. В качестве еще одного примера можно привести Индекс Токийской фондовой биржи, движения которого также нестабильны и при этом динамика отрицательна.&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101860/003.JPG/" alt="График индекс Токийской фондовой биржы" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Отметим, что и рост Индекса Доу-Джонса на три порядка за 100 лет на самом деле не такой уж впечатляющий: если усреднить весь рост с 1933 года (дно краха 1929 года) по сегодняшний день и пересчитать в годовые приросты – получится рост всего 8 % годовых.&lt;/p&gt;
&lt;p&gt;**:::center
Закономерность 2. В летние месяцы наблюдается снижение активности фондового рынка&lt;/p&gt;
&lt;div class="**"&gt;&lt;p&gt;С приближением лета в СМИ все чаще упоминается «летнее затишье». Об этом пишут аналитики и говорят комментаторы на РБК. Согласно этим сообщениям получается, что у фондового рынка тоже есть своеобразный период отпусков.
На самом деле, для того, чтобы доказать, что нет такого понятия как «отпуск рынка», можно даже не использовать сложные алгоритмы вычислений. На примере изменений индекса РТС с 2000 по 2011 год была применена простая методика, которая позволяет определить удельный вес диапазона, пришедшегося на период отпусков с июня по август по отношению к диапазону всего года.&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101861/3.PNG/" alt="Расчет активности рынка в летние месяцы" /&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Исходя из данных таблицы, делаем следующий вывод: в среднем почти половина годового диапазона (49%) приходится на 3 летних месяца. Это значит, что лето – самый динамичный период в году.&lt;/p&gt;
&lt;p&gt;**:::center
Закономерность 3. Пятница – день фиксации прибыли, рынок в пятницу падает&lt;/p&gt;
&lt;div class="**"&gt;&lt;p&gt;К такому выводу пришли некоторые трейдеры и аналитики. Можно рассчитать, действительно ли для российского рынка характерно снижение котировок по пятницам.
Рассчитаем, сколько было понедельников за последние 10 лет, когда торги закрывались в плюс, и сколько было понедельников, которые закрывались в минус; аналогично посмотреть статистику для каждого дня недели, для чего используем котировки индекса РТС с 2000 года по 2011 год.&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101862/099.PNG/" alt="Расчет активности рынка по дням недели" /&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;В итоге приходим к следующему выводу: самым падающим днем является среда, именно в среду котировки росли всего лишь в 47% случаев, самыми растущими были понедельники и четверги. Цены повышались в эти дни соответственно в 56,8% и 55,4% случаев.
Как видно, пятницу ни в коем случае нельзя назвать днем, когда надо открывать короткие позиции, только потому, что большинство будет фиксировать прибыль, иначе бы в 54,3% случаев рынок бы не закрывался в эти дни в плюс.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>https://stocksharp.ru/topic/350/</id>
    <title type="text">Статистические модели трендов. Смещение среднего.</title>
    <published>2012-04-03T14:11:29Z</published>
    <updated>2012-12-17T14:41:07Z</updated>
    <author>
      <name>vlad1024</name>
      <uri>https://stocksharp.ru/users/768/</uri>
      <email>info@stocksharp.ru</email>
    </author>
    <category term="Алготрейдинг" />
    <category term="Статьи" />
    <content type="html">&lt;p&gt;Попросили объяснить без специальных терминов, что такое персистентность и как она связана с трендовостью рынка. Совсем без терминов вряд ли получится, но если их минимизировать, то достаточно одного понятия — плотность вероятности.&lt;/p&gt;
&lt;p&gt;Плотность вероятности — это функция, интеграл интервала которой дает нам вероятность попадания в этот интервал. Или, в простейшем случае, если мы рассматриваем ее эмпирическую оценку в виде гистограммы распределения, это будет просто частота попадания в набор фиксированных интервалов.
Для примера рассмотрим гистограмму нормального распределения.&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101834/img1.png/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Собственно, что мы видим — это разбиение на набор фиксированных интервалов, затем подсчет попадания каждого значения в тот или иной интервал, который дает частоту. Если мы хотим посчитать частоту попадания в бОльший интервал (например от 0 до 2), то нам необходимо сложить(проинтегрировать) частоту попадания во все маленькие интервалы внутри этого отрезка [0, 2]. Таким образом плотность вероятности дает возможность, зная интервал, получить вероятность попадания в него. Или, если рассматривать на более «интуитивном» уровне, — показывает, какие значения выпадают более часто, а какие менее. В приведенном примере наиболее часто выпадают значения вокруг нуля распределения, а затем оно постепенно спадает.&lt;/p&gt;
&lt;p&gt;Если мы рассмотрим распределение как набор значений, расположенных во времени (привычные для трейдинга представления в виде графиков числовых рядов), то получим для все того же нормального (гауссового) распределения следующую картинку:&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101835/img2.png/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Как и ожидалось из гистограммы распределения, 95% значений находятся внутри интервала от -2 до +2 с центром в 0.&lt;/p&gt;
&lt;p&gt;Каждый наверняка видел график случайного блуждания, а этот на него мало похож. Разница в том, что для того чтобы получить случайное блуждание, необходимо последовательно сложить эти значения. Или, наоборот, чтобы получить из случайного блуждания распределение приращений, необходимо взять разность соседних значений.&lt;/p&gt;
&lt;p&gt;Таким образом, мы подходим к первой простейшей модели тренда. Рассмотрим такое распределение приращений:&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101836/img3.png/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;На глаз оно практически не отличается от предыдущего, но среднее (центр) значение сдвинуто на +0.1. Теперь просуммируем значения распределений для первого случая с нулевым и положительным (+0.1) смещением среднего. Так мы получим два графика случайных блужданий.&lt;/p&gt;
&lt;p&gt;Первый график (без смещения в мат. ожидании приращений):&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101837/img4.png/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;И второй график (с «ничтожным»,ели различимым на графике распределения приращений, смещением +0.1):&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101838/img5.png/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Разница разительная, но на первом графике заработать не возможно, а на втором — вполне.&lt;/p&gt;
&lt;p&gt;В данном случае мы рассматриваем зависимость (смещение в мат. ожидании), которая не изменяется во времени, то есть стационарна, и равняется 0 для всего графика, или +0.1 — другого. Теперь представим, что эти значения сами изменяются во времени и представляют, например, кусочно-постоянную функцию, т.е. набор констант, из которого мы выбираем значение, действующее на каком-то интервале. Соответственно, если это значение положительное, возникает «растущий кусок тренда», если отрицательное — «падающий». А сам график «сшит» из таких интервалов с постоянными значениями. Таким образом мы получим приближенную к реальности простейшую динамическую модель тренда, у которой стационарное среднее приращений равняется 0, но при этом существуют интервалы, на которых оно отклоняется от 0 как в положительную, так и отрицательную сторону. При этом в среднем количество таких участков «уравновешивается», и мы получаем среднее всех приращений близким к 0.&lt;/p&gt;
&lt;p&gt;Или если мы будем рассматривать среднее как функцию времени, то для кусочно-постоянной модели получим следующую картинку:&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101839/img6.png/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Или ввиде формулы: P_i+1 = P_i + A_k + N(0, 1) , где
A_k — это значение среднего на данном временном интервале (t_k, t_k+1),
N(0, 1) — стандартизированное нормальное распределение,
Pi — это получившийся стохастический процесс.&lt;/p&gt;
&lt;p&gt;Для примера рассмотрим реализацию такого стохастического процесса, при t_k = (0, 100, 200, 400, 450, 600, 650) и A_k = (+0.1, -0.1, +0.05, +0.15, -0.2, -0.05), что примерно соответствует представленному выше графику зависимости от времени.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Первая реализация:&lt;/strong&gt;&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101840/img7.png/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Вторая реализация:&lt;/strong&gt;&lt;/p&gt;
&lt;div style="text-align:center"&gt;&lt;p&gt;&lt;img src="/file/101841/img8.png/" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Как видно, они мало похожи и в них гораздо менее очевидно наличие трендов по сравненинию с простейшим стационарным случаем, но, тем не менее, они там присутствуют, а значит на таком процессе возможно заработать.&lt;/p&gt;
&lt;p&gt;В следующей статье мы поговорим о еще одной модели тренда, которая связана с персистентностью. Точнее, мы будем понимать под персистентностью авто-регрессивность числового ряда.&lt;/p&gt;
</content>
  </entry>
</feed>