Стратегия торговли сетями
(www.fmz.com)
Основная идея торговли по сетке очень проста. Вместо того, чтобы размещать одну торговлю, мы размещаем несколько сделок, образующих сетку. Обычно они вводятся как
Что такое сетевая торговля и как она работает? Торговля по сетке - это игра волатильности рынка. Есть две причины, по которым она предпочтительна трейдерам. Первая заключается в том, что она не требует от вас окончательного прогноза направления рынка.
Во-вторых, он хорошо работает на волатильных рынках, где нет четкой тенденции.
Торговля по сетке - это вид технического анализа, основанный на движении в рамках определенных моделей сетки. Торговля по сетке популярна в валютной торговле. В целом техника стремится извлечь выгоду из нормальной волатильности цен на рынках путем размещения ордеров на покупку и продажу в определенные регулярные интервалы выше и ниже заранее определенной базовой цены. Такие ордера на покупку и продажу, обычно размещенные на 10 или 15 единиц интервалов, создают торговую сетку.
Решетка может настроить направление
Основная торговая операция: сначала покупать, а затем продавать.
Решетка начнет отправлять ордер на покупку по цене ниже первой цены, которая является ценой, за которой следует первая цена (вторая последняя цена покупки, третья последняя цена покупки и так далее).
После завершения любого заказа на покупку, программа будет на основе покупной цены, добавить цену параметра
Сначала продавать коротко, а затем покупать для покрытия: операция прямо противоположная
Наибольший риск этой стратегии заключается в том, что рыночная тенденция является односторонней, а колебания цен превышают сетку.
Следующий код создал сетку с автоматической функцией остановки и движения.
Примечания:
Стратегия использует виртуальный дизайн ожидаемых заказов, который обеспечивает большую обработку для биржи, чтобы ограничить количество ожидаемых заказов, и гибко решает проблему.
Логика сетки гибкая по конструкции и умная по структуре.
Расчет прибыли и убытка, каждый численный статистический алгоритм может быть использован в качестве ссылки, и каждый дизайн обнаружения состояния является строгим. (для минимизации возможности BUG)
Исходный код очень стоит изучить.
Для получения дополнительной информации см.
https://www.fmz.com/strategy/112633
Источник:
// Исходный код: /* Параметры интерфейса (показаны как глобальные переменные в коде) OpType Grid Direction Drop-down box (selected) Купить сначала, а потом продать. FirstPriceAuto начальная цена автоматическая булевая (правда/ложно) true FirstPrice@!FirstPriceАвтоматическая начальная цена (номер) 100 Все число общее число числовое (число) 10 PriceGrid Ценовой интервал (число) 1 Численный спред PriceDiff (число) 2 СуммаТип размера заказа выпадающее окно (выбранное) купить и продать одну и ту же сумму AmountOnce@AmountType==0 Количество единичной сделки BAmountOnce@AmountType==1 Размер заказа на покупку SAmountOnce@AmountType==1 Размер ордера на продажу (число) 0.1 AmountCoefficient@AmountType==0 Разница количества Структура (структура) *1 AmountDot Число с запятой (число) 3 EnableProtectDiff Включить защиту от распространения Булево (правда/ложно) ложно ProtectDiff@EnableProtectDiff Входный спред Числовая защита цены (номер) 20 CancelAllWS stop отменяет все ожидающие заказы Булева (правда/ложно) true CheckИнтервал избирательного интервала номер (номер) 2000 Неудача интервала перепробовать интервал числовой (номер) 1300 RestoreProfit восстанавливает последнюю прибыль Булево (правда/ложно) ложно Последняя прибыль@Восстановление прибыли Последняя прибыль числовая (число) 0 ProfitAsOrg@RestoreProfit Последняя прибыль учитывается как средняя цена Булева (правда/ложно) ложная EnableAccountCheck включить проверку баланса Булева (правда/ложно) true EnableStopLoss@EnableAccountCheck открыть Stop Loss Булева (правда/ложно) ложно StopLoss@EnableStopLoss максимальная плавающая потеря (число) 100 StopLossMode@EnableStopLoss Операция после остановки потери Выпадающее окно (выбранное) Перезагрузить и выйти EnableStopWin@EnableAccountCheck Включить прием прибыли Булева (правда/ложно) ложь StopWin@EnableStopWin Максимальная плавающая прибыль Тип номера (номер) 120 StopWinMode@EnableStopWin после операции по получению прибыли выпадающее окно (выбранное) Перерабатывать и выходить. AutoMove@EnableAccountПроверка автоматического перемещения Булево (правда/ложно) ложно MaxDistance@AutoMove максимальное числовое расстояние (число) 20 MaxIdle@AutoMove максимальная безработная работа (секунды) числовая (число) 7200 EnableDynamic Поворачивает динамические ожидающие заказы Булева (правда/ложно) ложно DynamicMax@EnableDynamic расстояние истечения срока действия ордера Номер (номер) 30 ResetData очищает все данные при запуске Булево (правда/ложно) true Длина десятичной цифры точности цены (число) 5 */
function hasOrder ((orders, orderId) { // Проверьте, есть ли порядок с идентификатором порядка в параметрах порядка for (var i = 0; i < orders.length; i++) { // Пройдите по командам, чтобы проверить, есть ли одинаковые идентификаторы, если есть, то верните true если (заказы[i].Id == orderId) { возвращает true; Я не знаю. Я не знаю. return false; // Все пройдено, нет триггера если означает не найдено порядка с ID orderId, возвращается false Я не знаю.
функция cancelPending() { // Отменить все ожидающие функции заказа var ret = false; // Установка переменной успешного тега возврата пока (правда) { // пока петля если (ret) { // Если ret является истинным, то сон в течение определенного времени Спящий ((Интервал); Я не знаю. var orders = _C(exchange.GetOrders); // Вызвать API, чтобы получить информацию о заказе, который обмен не выполнял. if (orders.length == 0) { // Если возвращается пустой массив, обмен не имеет неисполненных заказов. Break; // Выйти из цикла while Я не знаю.
for (var j = 0; j < orders.length; j++) { // Traverse the unfinished order array and use orders[j].Id one by one to cancel the order based on the index j.
exchange.CancelOrder(orders[j].Id, orders[j]);
ret = true; // Once there is a cancel operation, ret is assigned a value of true. Used to trigger above Sleep, wait for re-exchange.GetOrders detection
}
}
return ret; // return ret
}
function valuesToString(values, pos) { // Значение, преобразованное в строку
var result =
Функция Trader() { // Функция Trader, использующая закрытия.
var vId = 0; // Идентификатор инкремента заказа
var orderBooks = []; // Книга заказов
var hisBooks = []; // Книга исторического порядка
var orderBooksLen = 0; // Длина книги заказов
this.Buy = function ((цена, сумма, дополнительная) { // Функция покупки, параметры: цена, количество, расширенная информация
if (typeof(extra) ===
if (orders[i].Id == order.Id) { // Когда вы находите порядок с тем же идентификатором порядка в orderBooks, назначьте значение true для поиска, что означает найти.
найдено = верно;
Break; // Выйти из текущей петли
Я не знаю.
Я не знаю.
if (!found) { // Если не найдено, нажмите orderBooks[orderId] на order.
orders.push ((orderBooks[orderId]); // Почему вы хотите нажать так?
Я не знаю.
Я не знаю.
ордера на возврат; // ордера на возврат
Я не знаю.
это.GetOrder = функция ((orderId) { // Получить порядок
if (typeof(orderId) ===
var pfn = order.Type == ORDER_TYPE_BUY ? exchange.Buy : exchange.Sell; // Assign the corresponding API function reference to pfn according to the type of the order.
// That is, if the order type is a buy order, pfn is a reference to the exchange.Buy function, the same as the sell order.
if (order.Id == 0 && diff <= priceDiff) { // If the order order in the order book is not activated (ie Id is equal to 0) and the current price is less than or
// equal to the order plan price, the priceDiff passed in the parameter.
var realId = pfn(order.Price, order.Amount, order.Extra + "(distance: " + diff + (order.Type == ORDER_TYPE_BUY ? (" ask price: " + ticker.Buy) : (" bid price: " + ticker.Sell))+")");
// Execute order function, parameter passing price, quantity, order extension information + pending order distance + market data (ask price or bid price), return exchange order id
if (typeof(realId) === 'number') { // If the returned realId is a numeric type
order.Id = realId; // Assign the Id attribute of the current order order to the order book.
}
} else if (order.Id > 0 && diff > (priceDiff + 1)) { // If the order is active and the current distance is greater than the distance passed in by the parameter
var ok = true; // Declare a variable for tagging Initially set true
do { // Execute "do" first and then judge while
ok = true; // Ok assign true
exchange.CancelOrder(order.Id, "unnecessary" + (order.Type == ORDER_TYPE_BUY ? "buying" : "selling"), "placed order price:", order.Price, "volume:", order.Amount, ", distance:",
diff, order.Type == ORDER_TYPE_BUY ? ("ask price: " + ticker.Buy) : ("bid price: " + ticker.Sell));
// Cancel the pending order that is out of range. After canceling the order, print the current order information and the current distance diff.
Sleep(200); // Wait 200 milliseconds
orders = _C(exchange.GetOrders); // Call the API to get an uncompleted order in the exchange.
for (var i = 0; i < orders.length; i++) { // Traverse these unfinished orders.
if (orders[i].Id == order.Id) { // If the cancelled order is found in the list of orders that have not been completed by the exchange
ok = false; // Assign ok this variable to false, that is, no cancellation is successful.
}
}
} while (!ok); // If ok is false, then !ok is true and while will continue to repeat the loop, continue to cancel the order,
// and check if the cancellation is successful.
order.Id = 0; // Assigning a value of 0 to order.Id means that the current order is inactive.
}
}
};
}
function balanceAccount ((orgAccount, initAccount) { // Balance Account Function Parameter Initial account information when the strategy is started) { // Balance Account Function Parameter Initial account information when the strategy is started } - функция баланса аккаунта (англ. баланс аккаунта) { // Balance Account Function Parameter Initial account information when the strategy is started)
cancelPending ((); // Call the custom function cancelPending (()) to cancel all pending orders (Вызвать настройку cancelPending (()) для отмены всех ожидаемых заказов.
var nowAccount = _C ((exchange.GetAccount); // Declare a variable nowAccount to record the latest information about the account at the moment. // Declare a variable nowAccount to record the latest information about the account at the moment. // Declare a variable nowAccount to record the latest information about the account at the moment. // Declare a variable nowAccount to record the latest information about the account at the moment. // Declare a variable nowAccount to record the latest information about the account at the moment.
var slidePrice = 0.2; // Set the slip price when placing the order as 0.2 - Установите слиповую цену при размещении ордера как 0.2
var ok = true; // Tag variable initially set true - переменная с тегом, изначально установленная как true
while (true) { // в то время как петля
var diff = _N ((nowAccount.Stocks - initAccount.Stocks); // Calculate the difference between the current account and the initial account diff (Вычислить разницу между текущим счетом и начальным счетом)
if (Math.abs(diff) < exchange.GetMinStock()) { // If the absolute value of the currency difference is less than the minimum transaction volume of the exchange, то это означает, что абсолютная стоимость валютной разницы меньше минимального объема транзакций на бирже.
// break выходит из цикла и не выполняет балансирующие операции.
"Я не хочу, чтобы ты был здесь".
{y:bi}
var depth = _C ((exchange.GetDepth); // Get the exchange depth information Определить объявленную переменную глубины
var books = diff > 0? depth.Bids : depth.Asks; // According to the difference of the currency is greater than 0 or less than 0, extract the buy order array or
// sell order array in depth (equal to 0 will not be processed, it is break when it is judged to be less than GetMinStock) // sell order array in depth (равный 0 не будет обработан, он будет нарушен, когда он будет оценен как меньше GetMinStock)
// The difference between the coins is greater than 0 to sell the balance, so look at the buy order array, так что если вы хотите продать баланс, вы должны продать его.
// the difference between the coins is less than 0 is the opposite. // the difference between the coins is less than 0 is the opposite. // the difference between the coins is less than 0 is the opposite.
var n = 0; // Statement n initial is 0
var price = 0; // Statement price initial 0 (Статья о цене начальной 0)
for (var i = 0; i < books.length; i++) { // Traversing the buy or sell order array
n += books[i].Amount; // Accumulate Amount (order quantity) for each order based on the index i traversed (Списывайте количество заказов для каждого заказа, основанного на индексе, через который я прошел)
if (n >= Math.abs ((diff)) { // If the cumulative order quantity n is greater than or equal to the currency difference, then: Если суммарное количество n больше или равно валютной разнице, то:
price = books[i].Price; // Get the price of the current indexed order, assign it to price (получить цену текущего индексированного заказа, назначить ее цене)
break; // Jump out of the current for traversal cycle (выйти из потока для прохождения цикла)
{y:bi}
{y:bi}
var pfn = diff > 0? exchange.Sell : exchange.Buy; // Pass the sell order API (exchange.Sell) or the next buy order API (exchange.Buy) reference to the declared pfn.
// на основе валютной разницы больше 0 или меньше 0
var amount = Math.abs(diff); // The amount of the order to be balanced is diff, the difference in the currency, assigned to the declared amount variable. // The amount of the order to be balanced is diff, the difference in the currency, assigned to the declared amount variable. // The amount of the order to be balanced is diff, the difference in the currency, assigned to the declared amount variable.
var price = diff > 0? (price - slidePrice) : (price + slidePrice); // The direction of buying and selling according to the difference in the currency, increase or decrease the
// Slip price based on the price (slip price is to make it easier to trade), and then assign it to price. // Слип цена основана на цене (слип цена для того, чтобы легче торговать), и затем назначить ее на цену
Log ((
var STATE_WAIT_OPEN = 0; // Используется для состояния каждого узла в fishTable var STATE_WAIT_COVER = 1; //... var STATE_WAIT_CLOSE = 2; //... var ProfitCount = 0; // Запись прибыли и убытка var BuyFirst = true; // Первоначальные параметры интерфейса var IsSupportGetOrder = true; // определить обменную поддержку функции GetOrder API, глобальной переменной, используемой для определения начала основной функции var LastBusy = 0; // Запишите последний обрабатываемый объект времени
функция setBusy() { // Установка времени занятости LastBusy = new Date(); // Назначить LastBusy на объект текущего времени Я не знаю.
функция isTimeout() { // Определить, если это время if (MaxIdle <= 0) { // Максимальное время простоя (в зависимости от того, перемещается ли сетка автоматически), // если максимальное время простоя MaxIdle меньше или равно 0 return false; // возвращает false, не оценивает времяпроход. то есть всегда возвращает false без временипрохода. Я не знаю. var now = new Date ((); // Получить объект текущего времени if (((now.getTime() - LastBusy.getTime()) / 1000) >= MaxIdle) { // Используйте функцию getTime текущего объекта времени для получения временной метки и временной метки LastBusy для расчета разницы, // Разделите на 1000, чтобы вычислить количество секунд между двумя объектами времени. // Определить, если это больше, чем максимальное время простоя MaxIdle LastBusy = сейчас; // Если он больше, обновление LastBusy к текущему объекту времени сейчас return true; // возвращает true, что является тайм-аутом. Я не знаю. return false; // Return false без отсрочки Я не знаю.
функция onexit() { // Функция закрытия при выходе программы.
if (CancelAllWS) { // Для отмены всех ожидаемых заказов при остановке вызовите cancelPending() для отмены всех ожидаемых заказов.
Журнал ((
Функция рыболовства ((orgСчет, рыбаСчет) { // Параметры литья: информация о счете, количество литья
setBusy(); // Настроить LastBuys на текущий временной штемпель
var account = _C(exchange.GetAccount); // Декларируйте переменную учетной записи, чтобы получить информацию о текущем счете и назначить ее.
Log ((account); // Выводит информацию об учетной записи в начале вызова в функцию рыболовства.
var InitAccount = account; // Декларируйте переменную InitAccount и назначьте ее с учетом.
// этот отлив, используется для расчета плавающей прибыли и убытка.
var ticker = _C(exchange.GetTicker); // Получить цену котировки, присвоенную объявленной переменной ticker
var amount = _N(AmountOnce); // В соответствии с количеством параметров интерфейса, используйте _N для обработки десятичных мест (_N по умолчанию до 2 бит) и присвоите их сумме.
var amountB = [amount]; // Декларировать переменную под названием amountB - массив, инициализировать элемент с amount
var amountS = [amount]; // Декларировать переменную под названием amountS...
if (typeof(AmountType)!==
Я не знаю.
// Инициализировать рыбную таблицу
var fishTable = {}; // Декларировать объект сетки
var uuidTable = {}; // Объект таблицы идентификационного кода
var needStocks = 0; // Необходимые монеты переменная
var needMoney = 0; // Требуемая денежная переменная
var actualNeedMoney = 0; // На самом деле нужны деньги
var actualNeedStocks = 0; // Действительно нужные монеты
var notEnough = false; // Недофинансируемая переменная тега, изначально установлена на false
var canNum = 0; // Доступная сетка
for (var idx = 0; idx < AllNum; idx++) { // Структура проходит в соответствии с числом сетки AllNum.
var price = _N((BuyFirst? FirstPrice - (idx * PriceGrid) : FirstPrice + (idx * PriceGrid)), точность);
// При прохождении конструкции текущая цена индекса idx устанавливается в соответствии с BuyFirst.
needStocks += amountS[idx]; // Количество проданных монет постепенно накапливается с циклом.
needMoney += price * amountB[idx]; // Сумма денег, необходимая для покупки, постепенно накапливается с циклом.
if (BuyFirst) { // Первое обращение с покупкой
если (_N(needMoney) <= _N ((account.Balance)) { // Если сетке требуется меньше денег, чем сумма денег, доступная на счете
actualNeedMondy = needMoney; // Назначен на фактическую сумму требуемых денег
actualNeedStocks = needStocks; // Назначение фактического количества требуемых монет.
canNum++; // Совокупное количество доступных сеток
} else { // _N(needMoney) <= _N ((account.Balance) Если это условие не выполнено, то переменная "underfunded" должна быть установлена на значение true
notEnough = true;
Я не знаю.
{ \ cHFFFFFF } иное { \ cHFFFFFF }
if (_N(needStocks) <= _N(account.Stocks)) { // Проверьте, меньше ли требуемое количество монет, чем количество монет, доступных на счете
actualNeedMondy = needMoney; // Назначение
actualNeedStocks = needStocks;
canNum++; // Совокупное количество доступных сеток
{ \ cHFFFFFF } еще { \ cHFFFFFF }
notEnough = true; // Установите true, если условия финансирования не выполнены
Я не знаю.
Я не знаю.
fishTable[idx] = STATE_WAIT_OPEN; // В соответствии с текущим индексом idx, установить состояние члена idx (узла сетки) объекта сетки,
// изначально STATE_WAIT_OPEN (в ожидании открытия позиции)
uuidTable[idx] = -1; // Номерированный объект также инициирует собственное значение idx (узло, соответствующее fishTable) до -1 на основе текущего idx.
Я не знаю.
if (!EnableAccountCheck && (canNum < AllNum)) { // Если проверка средств не включена, и количество сеток (общее количество узлов), где узел меньше
// чем настройка параметров интерфейса может быть открыта.
Log ((
бросить
var trader = new Trader(); // Constructs a Trader object, assigning it to the trader variable declared here.
var OpenFunc = BuyFirst ? exchange.Buy : exchange.Sell; // According to whether to buy and sell first, set the open function OpenFunc to refer to exchange.Buy or exchange.Sell
var CoverFunc = BuyFirst ? exchange.Sell : exchange.Buy; // same as above
if (EnableDynamic) { // Set OpenFunc/CoverFunc again according to whether the interface parameter EnableDynamic is enabled.
OpenFunc = BuyFirst ? trader.Buy : trader.Sell; // The member function Buy that references the trader object is used for dynamic pending orders (mainly because
// some exchanges limit the number of pending orders, so virtual dynamic pending orders are required)
CoverFunc = BuyFirst ? trader.Sell : trader.Buy; // same as above
}
var ts = new Date(); // Create a time object at this time (assigned to ts) to record the time at the moment.
var preMsg = ""; // Declare a variable to record the last message, the initial set to empty string
var profitMax = 0; // Maximum return
while (true) { // The main logic after the grid is casted
var now = new Date(); // Record the time when the current cycle started
var table = null; // Declare a variable
if (now.getTime() - ts.getTime() > 5000) { // Calculate whether the difference between the current time now and the recorded time ts is greater than 5000 milliseconds
if (typeof(GetCommand) == 'function' && GetCommand() == "Receiving grid") { // Check if the strategy interaction control command "receives the grid" is received,
// stops and balances to the initial state.
Log("Start executing commands to perform grid operations"); // Output information
balanceAccount(orgAccount, InitAccount); // Perform a balancing function to balance the number of coins to the initial state
return false; // This time the grid function is fishing and return false
}
ts = now; // Update ts with current time now for next comparison time
var nowAccount = _C(exchange.GetAccount); // Declare the nowAccount variable and initially been set as the current account information.
var ticker = _C(exchange.GetTicker); // Declare the ticker variable and initially been set as the current market information.
if (EnableDynamic) { // If you enable dynamic pending orders
trader.Poll(ticker, DynamicMax); // Call the Poll function of the trader object to detect and process all orders based on the
// current ticker market and the interface parameter DynamicMax.
}
var amount_diff = (nowAccount.Stocks + nowAccount.FrozenStocks) - (InitAccount.Stocks + InitAccount.FrozenStocks); // Calculate the current coin difference
var money_diff = (nowAccount.Balance + nowAccount.FrozenBalance) - (InitAccount.Balance + InitAccount.FrozenBalance); // Calculate the current money difference
var floatProfit = _N(money_diff + (amount_diff * ticker.Last)); // Calculate the current floating profit and loss of this time of casting grid
var floatProfitAll = _N((nowAccount.Balance + nowAccount.FrozenBalance - orgAccount.Balance - orgAccount.FrozenBalance) + ((nowAccount.Stocks + nowAccount.FrozenStocks
- orgAccount.Stocks - orgAccount.FrozenStocks) * ticker.Last));
// Calculate the overall floating profit and loss
var isHold = Math.abs(amount_diff) >= exchange.GetMinStock(); // If the absolute value of the coin difference at this moment is greater than the minimum trading
// volume of the exchange, it means that the position has been held.
if (isHold) { // If you have already held a position, execute the setBusy() function, which will update the LastBusy time.
setBusy(); // That is, after opening the position, the opening of the opening mechanism is started.
}
profitMax = Math.max(floatProfit, profitMax); // Refresh the maximum floating profit and loss
if (EnableAccountCheck && EnableStopLoss) { // If you initiate account detection and start a stop loss
if ((profitMax - floatProfit) >= StopLoss) { // If the maximum floating profit or loss minus the current floating profit or loss is greater than or equal to
// the maximum floating loss value, execute the code inside the curly braces
Log("Current floating profit a