Документация к данному терминалу мне показалась очень скудной. Особенно в части разработки индикаторов, роботов. Хотел бы описать процесс создания/добавления собственного индикатора на простом примере.
Для работы с собственными индикаторами в терминале идем в меню Charts& Quotes -> Custom Indicators -> Indicator Store:
Оптимизация в Wealth-lab, как известно, использует только одно ядро одного процессора и только один поток одновременно. Такой подход не позволяет использовать всю мощь современных компьютеров, что очень расстраивает алготрейдеров. Многие устали атаковать службу поддержки с вопросом «Когда многопоточность будет внедрена в Wealth-lab» и разработчики написали свою библиотеку для оптимизации.
Я выкладываю скомпилированную библиотеку, а также проект на Visual Studio 2015, с открытым кодом. Ссылка на форум, где обсуждался и разрабатывался этот код.
После того, как вы скачали библиотеку, скопируйте ее в папку с Wealth-lab (по умолчанию программа расположена по слудующему пути: «c:\Program Files\MS123\Wealth-Lab Developer 6\»)
Если Wealth-lab у вас был запущен, то перезапустите его. После перезапуска в разделе оптимизации у вас появится новый пункт Parralel Optimizer (Exhaustive):
Давно замечал за моим брокером отставание графика. Т.е. данные на график поступают с задержкой. Первый раз обнаружил при поиске косяка в одном из роботов. Потом увидел на графике, но задержки были не большими. Сегодня задержка была длительной и отставание от реального времени составило более 5 минут. Скорость интернета:
Занимался разработкой сигнального сервиса. Вся работа на получение и отправку сообщений легла в отдельную .dll. На чарте висит индикатор, который подключает эту .dll и через нее отправляет информацию о сделках. Сигналы отправлялись нормально, но получать библиотека ничего не хотела. Вываливалась с исключением «Невозможно загрузить файл или сборку...» и ссылалась на имя моей библиотеки. Я долго не понимал, как это так. Сама библиотека внутри себя ищет себя же… И при этом не может найти. Писал в поддержку нинзи, на что получил ответ, что ваша библиотека закрыта и ее сложно отладить… :) Начал копаться сам и нашел следующее: когда я в индикаторе использую библиотеку, то NinjaTrader грузит ее из папки «C:\Users\[UserName]\Documents\NinjaTrader 7\bin\Custom\», но когда в этой библиотеке вызывается определенный код, то NinjaTrader ищет эту библиотеку в папке «С:\Program Files (x86)\NinjaTrader 7\bin64\».
//Читаем их Excel данные в массив List getParamsFromExcel(string filePath) { //С какой строки начинаем читать данные int start_from_row = 2; //Индекс колонки с Тикером int symbol_index = 1; //Индекс колонки с типом ордера int order_type_index = 2; //Индекс колонки с ценой входа int entry_price_index = 4; //Индекс колонки с ценой стопа int stop_price_index = 5; //Индекс колонки с временем входа int entry_time_index = 7; int current_index = start_from_row; //Текущий символ графика string read_symbol = Bars.Symbol; //Текущий считанный из Excel символ string current_symbol; //Список параметров считанный из Excell List result; result = new List(); //Переменная Excel приложение Excel.Application xlApp; //Переменная рабочая книга Excel.Workbook xlWorkBook; //Переменная рабочий лист Excel.Worksheet xlWorkSheet; //Переменная диапазон Excel.Range range; //Инициализируем переменные xlApp = new Excel.Application(); xlWorkBook = xlApp.Workbooks.Open(filePath); xlWorkSheet = xlWorkBook.Worksheets.get_Item(1); range = xlWorkSheet.UsedRange; //Считываем тикер из Excel current_symbol = (string)(range.Cells[current_index, symbol_index] as Excel.Range).Value2; //Читаем тикеры, пока не наткнемся на пустую строку while(current_symbol != null) { //Если считанный тикер совпадает с тикером графика, на котором запустили робота if(read_symbol == current_symbol) { //Читаем и добавляем параметры ордера result.Add(new OrderParams { ePrice = Convert.ToDouble((range.Cells[current_index, entry_price_index] as Excel.Range).Value2), sPrice = Convert.ToDouble((range.Cells[current_index, stop_price_index] as Excel.Range).Value2), eTime = DateTime.FromOADate((range.Cells[current_index, entry_time_index] as Excel.Range).Value2), pType = ((string)(range.Cells[current_index, order_type_index] as Excel.Range).Value2 == "Short" ? PositionType.Short : PositionType.Long) }); } current_index++; //Считываем очередной тикер current_symbol = (string)(range.Cells[current_index, symbol_index] as Excel.Range).Value2; } //Закрываем рабочую книгу xlWorkBook.Close(true, null, null); //Выходим из приложения xlApp.Quit(); //Уничтожаем созданные объекты releaseObject(xlWorkSheet); releaseObject(xlWorkBook); releaseObject(xlApp); return result; } //Уничтожаем переданный объект private void releaseObject(object obj) { try { System.Runtime.InteropServices.Marshal.ReleaseComObject(obj); obj = null; } catch (Exception ex) { obj = null; } finally { GC.Collect(); } }