В чем состоит смысл понятия авторегрессивности / автокорреляции / персистентности? Расмотрим простейший процесс, в котором последующие приращения зависят от предыдущего. Обозначим приращение в момент времени t — X_t, в момент времени t + 1 — X_t+1. Соответственно, мы хотим, чтобы приращение в момент времени t+1 каким-то образом зависело от предыдущего t. Если выразить такую зависимость качественно, то у нас есть два варианта. Первый вариант Мы предполагаем, что положительное приращение X_t должно увеличивать вероятность положительного приращения в следующий момент времени X_t+1 и аналогично для отрицательного. Проще говоря, Х_t и X_t+1 положительно скоррелированны. Такая модель является «трендовой, персистентной», то есть покупая/продавая то, что растет/падает, мы смещаем вероятность выигрыша в свою сторону. Второй вариант Мы предполагаем, что положительные приращения X_t должны увеличивать вероятность отрицательных в момент времени X_t+1, а отрицательные приращения — положительных. То есть X_t и X_t+1 отрицательно скоррелированны. Такая моделья является «контр трендовой, анти-персистентной», то есть продавая то, что выросло и покупая то, что упало, мы получаем статистическое преимущество. Соответственно, если закодировать эти наблюдения в виде общей формулы мы получим: X_t+1 = C + A*X_t + W_t, где С — это смещение мат. ожидания, A — коэффициент авторегрессии, W — белый (к примеру, гаусовский) шум. Для простоты предположим, что C = 0; тогда при A \u003e 0 получим первый вариант из расмотренных выше, а при A 1, модель теряет устойчивость, что характеризуется взрывным (экспоненциальным) ростом/падением или расширяющимися колебаниями с экспоненциальным ростом амплитуды. Если еще больше расширить модель, то в общем случае она может зависеть от нескольких значений в предыдущей истории, то есть зависимость будет иметь вид: X_t+1 = C + A1*X_t + A2*X_t-1 + A3*X_t-2 +… + Ai*X_t-i-1, но мы ограничимся рассмотрением случая с единичным лагом и C=0 как наиболее характерного. Теперь рассмотрим, как этот простейший пример будет выглядеть. Для этого возьмем исходный гауссовский шум: 101842 И применим к нему нашу AR(1) (авторегрессивность с 1 лагом) модель с С=0 и с различными значениями A. При A=0.9 получим следующее (сверху — результат авторегрессивной модели приращений, снизу — интеграл этих приращений + аддативный шум, то есть приближение к случайному блужданию рыночной модели): 101843 Та же самая модель при A=0.15: 101844 Зависимость слабая, но несмотря на это, хорошо видно, как возникают локально-трендовые участки на графике. Так жеесли мы построим облако точек, где по оси X — приращение X_t, а по Y — приращение X_t-1, эта зависимость будет отчетливо видна: 101845 Теперь переходим к оставшейся части. Очевидно, что стационарных зависимостей на рынке нет, поэтому автокорреляционная функция приращений имеет тривиальный вид. Из этого следует, что такие зависимости могут быть описаны лишь, в лучшем случае, нестационарными моделями, то есть такими, в которых вид этой локальной зависимости не остается постоянным, а изменяется время от времени. Аналогично введенной в предыдущем посте «Статистические модели трендов. Смещение среднего», мы можем ввести кусочно-постоянную функцию, но на этот раз она будет описывать не смещение среднего, а значение коэффициента регрессии A. Таким образом можно получить участки, на которых авторегрессия носит локально-трендовый характер (A\u003e0), на других — локально-контртрендовый (A\u003c0), чтобы в конечном итоге удовлетворить наше условие тривиальности АКФ.
По x - время в минутах с начала сессии (10:00) образования хая, по y - дельта от опена до хая (day high - day open). Данные за 2010-11 годы. 101850 Аналогично но для лоя, по x - время в минутах с начала сессии (10:00) образования лоя, по y - дельта от опена до лоя (day open - day low). 101851
В реальном приложении у нас будет много стратегий со своими параметрами, которые проще всего загрузить из XAML файла. XAML — это декларативный язык разметки. Он упрощает создание пользовательского интерфейса для нашего приложения. К настоящему моменту мы уже проделали большую работу по разделению бизнес-логики от UI и теперь можем в форме писать кода типа: StandardStrategy strategy; StandardStrategy CreateStrategy() { var strategy = new StrikeStrategy() { TraderBuilder = new QuikTraderBuilder() { Path = \"***\", Login = \"***\", Password = \"***\" }, PortfolioSelector = new PortfolioSelector() { PortfolioName = \"***\" }, SecuritySelector = new SecuritySelector() { SecurityCode = \"RIM2\" }, HistoryCandleProvider = new FinamHistoryCandleProvider() { TimeFrame = TimeSpan.FromHours(1), FinamSecurityCode = 80996 }, SettingsProvider = new RegistrySettingsProvider() { SubKey = @\"Software\\FinDirector\\StrikeStrategy\" }, 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 \u0026\u0026 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(); } Получилось совсем немного кода. Тем не менее в реальном приложении у нас будет много стратегий и у каждой будет куча параметров. Чтобы не зашивать их в коде, проще всего загрузить их из XAML файла, таком как в примере из статьи “Создание роботов с помощью S#. Введение”. 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)); } } public class StrategyList : List { } Теперь изменим метод CreateStrategy нашей формы: StandardStrategy CreateStrategy() { var strategy = StrategyLoader.Load(\"Strategies.config\").Strategies.FirstOrDefault(); return strategy; } А в файл Strategies.config поместим все настройки. В коде формы теперь нет ничего лишнего. Автор статьи: Вадим Чижов
Самое главное в роботе — это обработка исключений. У нас в роботе могут быть запущено множество различных стратегий, и исключение в одном из роботов или ошибка в UI потоке не должны приводить к падению всей программы. Тем не менее именно такое поведение характерно по умолчанию для .NET программы. Далее считаем, что наш робот является WPF – приложением! В качестве теста используем следующий код: private void Window_Loaded(object sender, RoutedEventArgs e) { Task.Factory.StartNew(ThrowException); ThrowException(); } void ThrowException() { throw new Exception(\"ops!\"); } Вначале мы кидаем исключение в отдельном потоке (а в стратегиях события могут вызываться асинхронно), а затем в UI потоке. Приложение упадет. Чтобы это исправить, необходимо сделать следующие правки. В файле App.xaml.cs написать: protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); #if (DEBUG != true) // Don\u0027t handle the exceptions in Debug mode because otherwise the Debugger wouldn\u0027t // 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, \"Неизвестная ошибка: {0}\", e.ToString()), \"FinDirector\", MessageBoxButton.OK, MessageBoxImage.Error); } } Тем не менее, это не спасет от крэша наше приложение при необработанных исключениях не в UI потоке. В файл app.confg необходимо добавить строки: Теперь: приложение не будет падать при не критических исключениях (таких как OutOfMemory, StackOverflow); мы получим сообщение об ошибке, а не проглотим его. Автор статьи — Вадим Чижов