Стратегия торговли высокочастотными фьючерсами на сырьевые товары, написанная на C++

Автор:Доброта, Создано: 2020-05-22 15:28:11, Обновлено: 2023-11-02 19:54:28

img

Penny Jump Стратегия высокочастотного трейдинга фьючерсов на сырьевые товары, написанная на C++

Резюме

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

Классификация стратегии высокой частоты

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

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

Какова стратегия "Пенни-Скамп"?

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

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

Принцип стратегии Penny Jump

Мы знаем, что на торговом рынке много розничных инвесторов, а также много крупных инвесторов, таких как: горячие деньги, государственные фонды, частные фонды и т. Д. Розничные инвесторы обычно имеют меньше средств, их заказы имеют очень мало влияния на рынок, они могут легко покупать и продавать торговую цель в любое время. Но для крупных фондов участвовать на рынке это не так просто.

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

Из-за этого огромного заказа, он выглядит неуклюже на рынке, иногда мы называем его "слонные заказы".

Selling Price 400.3, Order volume 50; buying price 400.1, Order volume 10. 

Внезапно этот громоздкий слон прыгает на рынок, и цена предложения была отправлена по цене 400.1.

Selling Price 400.3, Order volume 50; Buying price 400.1, Order volume 510.

Трейдеры все знают, что если есть огромное количество ожидаемых ордеров по определенной цене, то эта цена будет формировать сильную поддержку ((или сопротивление).

Selling Price 400.3, Order volume 50; Buying price 400.2, Order volume 1,

цена 400.1 становится ценой Buying 2 в глубине ордерной книги. затем, если цена поднимется до 400.3, высокочастотный трейдер заработает прибыль в размере 0.1.

Даже если цена не повысится, в позиции покупки 2, все равно есть слон, удерживающий цену, и он может быть быстро продан обратно слону по цене 400.1. Это общая идея стратегии Penny Jump. Ее логика такая же простая, как это, путем мониторинга состояния рыночного заказа, чтобы спекулировать намерениями оппонента, а затем взять на себя руководство в построении благоприятной позиции, и, наконец, получить прибыль от небольшого спреда за короткий промежуток времени. Для этого слон, поскольку он вешает огромное количество ордера на покупку на рынке, он разоблачил свои торговые намерения и естественно стал охотничьей мишенью высокочастотных трейдеров.

Внедрение стратегии Penny Jump

Во-первых, наблюдать торговые возможности с очень низкой вероятностью рынка, и сделать соответствующие стратегии в соответствии с логикой торговли. Если логика сложна, вам нужно использовать существующие математические знания, использовать модель, чтобы описать природу иррационального явления, насколько это возможно, и минимизировать переподборку. Кроме того, это должно быть проверено механизмом обратного тестирования, который может соответствовать принципу Price first then Volume first. К счастью, у нас есть платформа FMZ Quant, которая в настоящее время поддерживает эти режимы обратного тестирования.

Что означает поддержка Price first then Volume first backtest engine? Вы можете понять это так: вы отправляете ожидаемый ордер на 400.1 для покупки, только когда цена продажи в глубине книги ордеров составляет 400.1 или ниже, ваш ожидаемый ордер может быть закрыт. Он только рассчитывает ценовые данные ожидаемых ордеров, и не рассчитывает объемные данные ожидаемых ордеров, который только отвечает ценовому приоритету ((цена первая) в правилах сопоставления обменных ордеров.

Volume first - это модернизированная версия price first. Он имеет приоритетное значение как для цены, так и для времени. Можно сказать, что этот режим совпадения точно такой же, как и модель обмена. Вычисляя сумму ожидаемого заказа, можно судить, достигает ли текущий ожидаемый заказ условия пассивной транзакции для реализации объемной транзакции, чтобы достичь реальной модели реальной рыночной среды.

Кроме того, некоторые читатели могут обнаружить, что стратегия Penny Jump требует рыночных торговых возможностей, то есть потребность рынка имеет по крайней мере два hop ценовых разрыва. При нормальных обстоятельствах основной торговый контракт товарных фьючерсов является относительно занятым. Разница между покупкой 1 и продажей 1hop заключается в том, что почти нет шансов на торговлю. Поэтому мы вкладываем свою энергию в суб-первичный контракт, где торговля не слишком активна. Этот тип торговых контрактов иногда имеет две или даже три hop возможности.

img

Продажа 1 цена 2225 с объемом 551, Покупка 1 цена 2223 с объемом 565, посмотрите вниз на несколько секунд. После этого это произойдет, оно исчезнет после нескольких тиков. В этом случае мы рассматриваем рынок как самокоррекцию. Что мы должны сделать, так это догнать. Перед тем как рынок активно исправит его. если мы сделаем это вручную, это было бы невозможно, с помощью автоматической торговли мы можем сделать это возможным.

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

Далее мы наблюдаем разницу между предыдущим Продажа 1 Покупка 1 и Покупка 1 Продажа 1 сейчас. Чтобы заполнить разрыв в ценах между рынком, если скорость достаточно быстра, он может быть помещен в авангарде других заказов. Кроме того, время удержания позиции очень короткое, с этой торговой логикой, после реализации стратегии, возьмите MA909 в качестве примера, реальный рыночный тест рекомендует Esunny вместо интерфейса CTP, механизм изменения позиции и ситуации фонда для Esunny заключается в подталкиваемых данных, очень подходящих для высокочастотного трейдинга.

Код стратегии

После устранения логики торговли мы можем использовать код для достижения этого. Поскольку платформа FMZ Quant использует C++ примеры написания стратегии слишком мало, здесь мы используем C++ для написания этой стратегии, которая удобна для каждого, чтобы научиться, и разнообразие - товары фьючерсные.fmz.com> Вход > Диспетчерская панель > Библиотека стратегии > Новая стратегия > Нажмите в выпадающем меню в левом верхнем углу > Выберите C++ для начала написания стратегии, обратите внимание на комментарии в коде ниже.

  • Шаг 1: Сначала создать структуру стратегии, в которой определены класс HFT и основная функция. Первая строка в основной функции - очистить журнал. Цель этого - очищать ранее запущенную информацию о журнале каждый раз, когда стратегия перезапускается. Вторая строка - отфильтровать некоторые сообщения об ошибках, которые не являются необходимыми, такие как задержка сети и некоторые советы, чтобы журнал записывал только важную информацию и выглядел более аккуратно; третья строка - распечатать сообщение Init OK, что означает, что программа начала запускаться. Четвёртая строка - создать объект в соответствии с классом HFT, и название объекта hft; пятая строка программы входит в петлю while, и всегда выполняет петлю в методе hft, можно увидеть, что метод Loop является логикой этой программы.

Далее, давайте посмотрим на класс HFT, который имеет пять методов. Первый метод - это метод конструкции; второй метод - это получить текущий день недели, чтобы определить, является ли это новой K-линией; третий метод - это в основном отменить все незаполненные ордера и получить подробную информацию о позиции, потому что перед размещением ордера сначала необходимо определить текущий статус позиции; четвертый метод в основном используется для печати некоторой информации, для этой стратегии этот метод не является основным; самый важный - пятый метод.

/ / Define the HFT class
Class HFT {
     Public:
         HFT() {
             // Constructor
         }
        
         Int getTradingWeekDay() {
             // Get the current day of the week to determine if it is a new K line
         }
        
         State getState() {
             / / Get order data
         }

         Void stop() {
             // Print orders and positions
         }
        
         Bool Loop() {
             // Strategy logic and placing orders
         }
};

// main function
Void main() {
     LogReset(); // clear the log
     SetErrorFilter("ready|timeout"); // Filter error messages
     Log("Init OK"); // Print the log
     HFT hft; // Create HFT object
     While (hft.Loop()); // enter loop
     Log("Exit"); // Program exits, prints the log
}

Итак, давайте посмотрим, как реализуется каждый из методов в этом классе HFT, и как работает самый основной метод Loop. Сверху вниз мы реализуем конкретную реализацию каждого метода один за другим, и вы обнаружите, что первоначальная стратегия высокой частоты очень проста. Прежде чем говорить о классе HFT, мы сначала определили несколько глобальных переменных для хранения результатов расчета объекта hft. Они: хранение статуса ордера, статус позиции, удержание длинной позиции, удержание короткой позиции, цена покупки, количество покупки, цена продажи, количество продажи. Пожалуйста, посмотрите код ниже:

/ / Define the global enumeration type State
Enum State {
     STATE_NA, // store order status
     STATE_IDLE, // store position status
     STATE_HOLD_LONG, // store long position directions
     STATE_HOLD_SHORT, // store short position direction
};

/ / Define global floating point type variable
Typedef struct {
     Double bidPrice; // store the buying price
     Double bidAmount; // store the buying amount
     Double askPrice; // store the selling price
     Double askAmount; // store the selling amount
} Book;

С помощью вышеперечисленных глобальных переменных мы можем хранить результаты, рассчитанные объектом hft отдельно, что удобно для последующих вызовов программой. Далее мы поговорим о конкретной реализации каждого метода в классе HFT. Во-первых, первый метод HFT - это конструктор, который вызывает второй метод getTradingWeekDay и распечатывает результат в журнале. Второй метод getTradingWeekDay получает текущий день недели, чтобы определить, является ли это новой K-строкой. Он также очень прост в реализации, получает часовую метку, вычисляет час и неделю, и, наконец, возвращает количество недель; третий метод getState немного длинный, я просто опишу общую идею, для конкретного объяснения вы можете посмотреть комментарии в следующем блоке кодирования.

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

Public:
    // Constructor
    HFT() {
        _tradingDay = getTradingWeekDay();
        Log("current trading weekday", _tradingDay);
    }
    
    // Get the current day of the week to determine if it is a new K line
    Int getTradingWeekDay() {
        Int seconds = Unix() + 28800; // get the timestamp
        Int hour = (seconds/3600)%24; // hour
        Int weekDay = (seconds/(60*60*24))%7+4; // week
        If (hour > 20) {
            weekDay += 1;
        }
        Return weekDay;
    }
    
    / / Get order data
    State getState() {
        Auto orders = exchange.GetOrders(); // Get all orders
        If (!orders.Valid || orders.size() == 2) { // If there is no order or the length of the order data is equal to 2
            Return STATE_NA;
        }
        
        Bool foundCover = false; // Temporary variable used to control the cancellation of all unexecuted orders
        // Traverse the order array and cancel all unexecuted orders
        For (auto &order : orders) {
            If (order.Id == _coverId) {
                If ((order.Type == ORDER_TYPE_BUY && order.Price < _book.bidPrice - _toleratePrice) ||
                    (order.Type == ORDER_TYPE_SELL && order.Price > _book.askPrice + _toleratePrice)) {
                    exchange.CancelOrder(order.Id, "Cancel Cover Order"); // Cancel order based on order ID
                    _countCancel++;
                    _countRetry++;
                } else {
                    foundCover = true;
                }
            } else {
                exchange.CancelOrder(order.Id); // Cancel order based on order ID
                _countCancel++;
            }
        }
        If (foundCover) {
            Return STATE_NA;
        }
        
        // Get position data
        Auto positions = exchange.GetPosition(); // Get position data
        If (!positions.Valid) { // if the position data is empty
            Return STATE_NA;
        }

        // Traverse the position array to get specific position information
        For (auto &pos : positions) {
            If (pos.ContractType == Symbol) {
                _holdPrice = pos.Price;
                _holdAmount = pos.Amount;
                _holdType = pos.Type;
                Return pos.Type == PD_LONG || pos.Type == PD_LONG_YD ? STATE_HOLD_LONG : STATE_HOLD_SHORT;
            }
        }
        Return STATE_IDLE;
    }
    
    // Print orders and positions information
    Void stop() {
        Log(exchange.GetOrders()); // print order
        Log(exchange.GetPosition()); // Print position
        Log("Stop");
    }

Наконец, мы сосредоточимся на том, как функция Loop управляет логикой стратегии и порядком. Если вы хотите более тщательно посмотреть, вы можете обратиться к комментариям в коде. Сначала определите, связаны ли транзакция CTP и сервер рынка; затем получите доступный баланс счета и количество недель; затем установите код сорта, который будет торговаться, вызвав официальную функцию FMZ SetQuantContractType, и можете использовать эту функцию для возвращения деталей торгового сорта; затем вызовите функцию GetDepth, чтобы получить данные о глубине текущего рынка. Глубинные данные включают: цену покупки, объем покупки, цену продажи, объем продажи и т. Д., и мы храним их с переменными, потому что они будут использоваться позже; Затем выведите эти данные в строку состояния порта, чтобы облегчить пользователю просмотр текущего состояния рынка; код выглядит следующим образом:

// Strategy logic and placing order
Bool Loop() {
    If (exchange.IO("status") == 0) { // If the CTP and the quote server are connected
        LogStatus(_D(), "Server not connect ...."); // Print information to the status bar
        Sleep(1000); // Sleep 1 second
        Return true;
    }
    
    If (_initBalance == 0) {
        _initBalance = _C(exchange.GetAccount).Balance; // Get account balance
    }
    
    Auto day = getTradingWeekDay(); // Get the number of weeks
    If (day != _tradingDay) {
        _tradingDay = day;
        _countCancel = 0;
    }
    
    // Set the futures contract type and get the contract specific information
    If (_ct.is_null()) {
        Log(_D(), "subscribe", Symbol); // Print the log
        _ct = exchange.SetContractType(Symbol); // Set futures contract type
        If (!_ct.is_null()) {
            Auto obj = _ct["Commodity"]["CommodityTickSize"];
            Int volumeMultiple = 1;
            If (obj.is_null()) { // CTP
                Obj = _ct["PriceTick"];
                volumeMultiple = _ct["VolumeMultiple"];
                _exchangeId = _ct["ExchangeID"];
            } else { // Esunny
                volumeMultiple = _ct["Commodity"]["ContractSize"];
                _exchangeId = _ct["Commodity"]["ExchangeNo"];
            }
            If (obj.is_null() || obj <= 0) {
                Panic("PriceTick not found");
            }
            If (_priceTick < 1) {
                exchange.SetPrecision(1, 0); // Set the decimal precision of the price and the quantity of the order.
            }
            _priceTick = double(obj);
            _toleratePrice = _priceTick * TolerateTick;
            _ins = _ct["InstrumentID"];
            Log(_ins, _exchangeId, "PriceTick:", _priceTick, "VolumeMultiple:", volumeMultiple); // print the log
        }
        Sleep(1000); // Sleep 1 second
        Return true;
    }
    
    // Check orders and positions to set status
    Auto depth = exchange.GetDepth(); // Get depth data
    If (!depth.Valid) { // if no depth data is obtained
        LogStatus(_D(), "Market not ready"); // Print status information
        Sleep(1000); // Sleep 1 second
        Return true;
    }
    _countTick++;
    _preBook = _book;
    _book.bidPrice = depth.Bids[0].Price; // "Buying 1" price
    _book.bidAmount = depth.Bids[0].Amount; // "Buying 1" amount
    _book.askPrice = depth.Asks[0].Price; // "Selling 1" price
    _book.askAmount = depth.Asks[0].Amount; // "Selling 1" amount
    // Determine the state of the port data assignment
    If (_preBook.bidAmount == 0) {
        Return true;
    }
    Auto st = getState(); // get the order data
    
    // Print the port data to the status bar
    LogStatus(_D(), _ins, "State:", st,
                "Ask:", depth.Asks[0].Price, depth.Asks[0].Amount,
                "Bid:", depth.Bids[0].Price, depth.Bids[0].Amount,
                "Cancel:", _countCancel,
                "Tick:", _countTick);
}

После того, как мы сделали так много, мы можем, наконец, размещение заказов. Перед торговлей, сначала мы судим текущее состояние позиции удержания программы (нет позиции удержания, длинные ордера позиции, короткие ордера позиции), здесь мы использовали если... иначе если... иначе если логический контроль. Они очень просты, Если нет позиции удержания, позиция будет открыта в соответствии с логическим условием. Если есть позиция удержания, позиция будет закрыта в соответствии с логическим условием. Для того, чтобы облегчить всем понимание, мы используем три абзаца, чтобы объяснить логику, Для части открытия позиции:

Сначала объявляем булевую переменную, мы используем ее для управления закрывающей позицией; далее нам нужно получить информацию о текущем счете и записать стоимость прибыли, затем определить статус ордера на вывод средств, если количество выводов превышает установленный максимум, напечатать соответствующую информацию в журнале; затем вычислить абсолютное значение текущей разницы цены предложения и предложения, чтобы определить, есть ли более 2 прыжков между текущей ценой предложения и ценой спроса.

Далее мы получаем купочную цену 1 и продажную цену 1, если предыдущая цена покупки больше текущей цены покупки, а текущий объем продажи меньше объема покупки, это означает, что цена покупки 1 исчезла. установлены цена открытия длинной позиции и количество ордера; в противном случае, если предыдущая цена продажи меньше текущей цены продажи, а текущий объем покупки меньше Объем продажи доказывает, что цена продажи 1 исчезла, установлены цена открытия короткой позиции и количество ордера; в конце концов, длинная позиция и короткие ордера входят на рынок одновременно.

Bool forceCover = _countRetry >= _retryMax; // Boolean value used to control the number of closings
If (st == STATE_IDLE) { // if there is no holding position
    If (_holdAmount > 0) {
        If (_countRetry > 0) {
            _countLoss++; // failure count
        } else {
            _countWin++; // success count
        }
        Auto account = exchange.GetAccount(); // Get account information
        If (account.Valid) { // If get account information
            LogProfit(_N(account.Balance+account.FrozenBalance-_initBalance, 2), "Win:", _countWin, "Loss:", _countLoss); // Record profit value
        }
    }
    _countRetry = 0;
    _holdAmount = 0;
    
    // Judging the status of withdrawal
    If (_countCancel > _cancelMax) {
        Log("Cancel Exceed", _countCancel); // Print the log
        Return false;
    }

    Bool canDo = false; // temporary variable
    If (abs(_book.bidPrice - _book.askPrice) > _priceTick * 1) { // If there is more than 2 hops between the current bid and ask price
        canDo = true;
    }
    If (!canDo) {
        Return true;
    }
    
    Auto bidPrice = depth.Bids[0].Price; // Buying 1 price
    Auto askPrice = depth.Asks[0].Price; // Selling 1 price
    Auto bidAmount = 1.0;
    Auto askAmount = 1.0;
    
    If (_preBook.bidPrice > _book.bidPrice && _book.askAmount < _book.bidAmount) { // If the previous buying price is greater than the current buying price and the current selling volume is less than the buying volume
        bidPrice += _priceTick; // Set the opening long position price
        bidAmount = 2; // set the opening long position volume
    } else if (_preBook.askPrice < _book.askPrice && _book.bidAmount < _book.askAmount) { // If the previous selling price is less than the current selling price and the current buying volume is less than the selling volume
        askPrice -= _priceTick; // set the opening short position volume
        askAmount = 2; // set the opening short position volume
    } else {
        Return true;
    }
    Log(_book.bidPrice, _book.bidAmount, _book.askPrice, _book.askAmount); // Print current market data
    exchange.SetDirection("buy"); // Set the order type to buying long
    exchange.Buy(bidPrice, bidAmount); // buying long and open position
    exchange.SetDirection("sell"); // Set the order type to selling short
    exchange.Sell(askPrice, askAmount); // short sell and open position
}

Далее мы поговорим о том, как закрыть длинную позицию, сначала установить тип ордера в соответствии с текущим статусом позиции, а затем получить цену Продажа 1. Если текущая цена Продажа 1 больше цены покупки длинной открытой, установить цену закрытия длинной позиции. Если текущая цена Продажа 1 меньше цены открытия длинной позиции, затем сбросить переменную количества закрытия на true, затем закрыть всю длинную позицию. Кодирование часть ниже:

Else if (st == STATE_HOLD_LONG) { // if holding long position
     exchange.SetDirection((_holdType == PD_LONG && _exchangeId == "SHFE") ? "closebuy_today" : "closebuy"); // Set the order type, and close position
     Auto sellPrice = depth.Asks[0].Price; // Get "Selling 1" price
     If (sellPrice > _holdPrice) { // If the current "selling 1" price is greater than the long position opening price
         Log(_holdPrice, "Hit #ff0000"); // Print long position opening price 
         sellPrice = _holdPrice + ProfitTick; // Set closing long position price
     } else if (sellPrice < _holdPrice) { // If the current "selling 1" price is less than the long position opening price
         forceCover = true;
     }
     If (forceCover) {
         Log("StopLoss");
     }
     _coverId = exchange.Sell(forceCover ? depth.Bids[0].Price : sellPrice, _holdAmount); // close long position
     If (!_coverId.Valid) {
         Return false;
     }
}

Наконец, давайте посмотрим, как закрыть короткую позицию. Принцип противоположный вышеупомянутой закрывающей длинной позиции. Во-первых, в соответствии с текущим состоянием позиции, установите тип ордера, а затем получите цену Покупка 1, если текущая цена Покупка 1 меньше цены открытия короткой позиции, будет установлена цена закрытия короткой позиции. Если текущая цена Покупка 1 больше цены открытия короткой позиции, сбросьте переменную количества закрытия на true, а затем закрыть все короткие позиции.

Else if (st == STATE_HOLD_SHORT) { // if holding short position
     exchange.SetDirection((_holdType == PD_SHORT && _exchangeId == "SHFE") ? "closesell_today" : "closesell"); // Set the order type, and close position
     Auto buyPrice = depth.Bids[0].Price; // Get "buying 1" price
     If (buyPrice < _holdPrice) { // If the current "buying 1" price is less than the opening short position price
         Log(_holdPrice, "Hit #ff0000"); // Print the log
         buyPrice = _holdPrice - ProfitTick; // Set the close short position price
     } else if (buyPrice > _holdPrice) { // If the current "buying 1" price is greater than the opening short position price
         forceCover = true;
     }
     If (forceCover) {
         Log("StopLoss");
     }
     _coverId = exchange.Buy(forceCover ? depth.Asks[0].Price : buyPrice, _holdAmount); // close short position
     If (!_coverId.Valid) {
         Return false;
     }
}

Выше приведен полный анализ этой стратегии.https://www.fmz.com/strategy/163427) для копирования полного исходного кода стратегии без настройки среды бэкстеста на FMZ Quant.

Результаты обратных испытаний

img

Логика торговли

img

Заявление о стратегии

Для того, чтобы удовлетворить любопытство высокочастотного трейдинга и более четко увидеть результаты, комиссия за транзакцию в среде обратного теста этой стратегии устанавливается на 0, что приводит к простой логике быстрой скорости. если вы хотите покрыть комиссию за транзакцию, чтобы достичь прибыльности на реальном рынке. Необходима дополнительная оптимизация. Например, использование потока заказов для проведения краткосрочного прогнозирования для улучшения выигрышной ставки, плюс возврат валютных сборов, Для достижения устойчивой прибыльной стратегии существует много книг о высокочастотном трейдинге. Я надеюсь, что каждый может больше думать и идти на реальный рынок, а не просто оставаться на принципе.

О нас

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


Связанные

Больше