Высокочастотная торговля - это сложная и конкурентная область, которая опирается на быстрое выполнение торгов и чувствительные понимания микроструктуры рынка. Одна из примечательных стратегий - Penny Jump, которая фокусируется на использовании слонов на рынке для получения небольших, но частых прибылей.
На фондовом рынке слоны обычно относятся к тем институциональным инвесторам, которые хотят купить или продать большое количество акций, но не хотят торговать по рыночной цене.
Например, предположим, что первоначальная глубина рынка акций была такой: 200 ∙ $1,01 х $1,03 ∙ 200. Затем входит "слон" и размещает ордер на покупку 3000 акций по $1,01 каждая. В этот момент глубина рынка изменится до 3,200 ∙ $1,01 х $1,03 ∙ 200. Это действие похоже на введение "слон", который становится центром внимания других участников рынка.
Конкурентный рынок Для высокочастотных трейдеров их прибыль в основном исходит из анализа микроструктуры рынка для спекуляций о намерениях других трейдеров. Как только появляется крупный игрок, высокочастотные трейдеры быстро устанавливают позиции, чтобы улавливать незначительные колебания цен. Их цель - часто торговать в течение короткого периода времени и накапливать небольшую, но накопительную прибыль.
Дилемма слона Несмотря на то, что слоны могут желать работать на рынке в больших масштабах, их действия также раскрывают их торговые намерения, что делает их мишенями для трейдеров с высокой частотой.
Обман на рынке В действительности крупные институциональные инвесторы обычно не размещают большое количество ордеров на покупку или продажу на рынке вопиюще, поскольку такое поведение может привести к тому, что другие участники рынка примут контрмеры или даже манипулируют рынком.
Основная идея стратегии Penny Jump заключается в том, что как только на рынке появляется
Не только это, но высокочастотные трейдеры также могут получать прибыль после покупки, даже если цена не повышается, потому что они знают, что крупный игрок поддержал базовую цену; следовательно, они могут быстро продать свои акции этому крупному игроку и получить небольшую арбитражную прибыль.
Источник стратегии:https://www.fmz.com/strategy/358
Код стратегии, приведенный выше, является примером, используемым для реализации стратегии Penny Jump. Ниже приведено подробное объяснение кода, позволяющее новичкам понять, как он работает:
var Counter = {
i: 0,
w: 0,
f: 0
};
// Variables
var InitAccount = null;
function CancelAll() {
while (true) {
var orders = _C(exchange.GetOrders);
if (orders.length == 0) {
break;
}
for (var i = 0; i < orders.length; i++) {
exchange.CancelOrder(orders[i].Id);
}
Sleep(Interval);
}
}
function updateStatus(msg) {
LogStatus("Number of debugging sessions:", Counter.i, "succeeded:", Counter.w, "failed:", Counter.f, "\n"+msg+"#0000ff\n"+new Date());
}
function main() {
if (DisableLog) {
EnableLog(false);
}
CancelAll();
InitAccount = _C(exchange.GetAccount);
Log(InitAccount);
var i = 0;
var locks = 0;
while (true) {
Sleep(Interval);
var depth = _C(exchange.GetDepth);
if (depth.Asks.length === 0 || depth.Bids.length === 0) {
continue;
}
updateStatus("Searching within the elephant... Buy one: " + depth.Bids[0].Price + ", Sell one:" + depth.Asks[0].Price + ", Lock times: " + locks);
var askPrice = 0;
for (i = 0; i < depth.Asks.length; i++) {
if (depth.Asks[i].Amount >= Lot) {
askPrice = depth.Asks[i].Price;
break;
}
}
if (askPrice === 0) {
continue;
}
var elephant = null;
// skip Bids[0]
for (i = 1; i < depth.Bids.length; i++) {
if ((askPrice - depth.Bids[i].Price) > ElephantSpace) {
break;
}
if (depth.Bids[i].Amount >= ElephantAmount) {
elephant = depth.Bids[i];
break;
}
}
if (!elephant) {
locks = 0;
continue;
}
locks++;
if (locks < LockCount) {
continue;
}
locks = 0;
updateStatus("Debug the elephant... The elephant is in gear " + i + ", " + JSON.stringify(elephant));
exchange.Buy(elephant.Price + PennyTick, Lot, "Bids[" + i + "]", elephant);
var ts = new Date().getTime();
while (true) {
Sleep(CheckInterval);
var orders = _C(exchange.GetOrders);
if (orders.length == 0) {
break;
}
if ((new Date().getTime() - ts) > WaitInterval) {
for (var i = 0; i < orders.length; i++) {
exchange.CancelOrder(orders[i].Id);
}
}
}
var account = _C(exchange.GetAccount);
var opAmount = _N(account.Stocks - InitAccount.Stocks);
if (opAmount < 0.001) {
Counter.f++;
Counter.i++;
continue;
}
updateStatus("Successful payment: " + opAmount +", Start taking action...");
exchange.Sell(elephant.Price + (PennyTick * ProfitTick), opAmount);
var success = true;
while (true) {
var depth = _C(exchange.GetDepth);
if (depth.Bids.length > 0 && depth.Bids[0].Price <= (elephant.Price-(STTick*PennyTick))) {
success = false;
updateStatus("Didn't get it, start to stop loss, currently buying one: " + depth.Bids[0].Price);
CancelAll();
account = _C(exchange.GetAccount);
var opAmount = _N(account.Stocks - InitAccount.Stocks);
if (opAmount < 0.001) {
break;
}
exchange.Sell(depth.Bids[0].Price, opAmount);
}
var orders = _C(exchange.GetOrders);
if (orders.length === 0) {
break;
}
Sleep(CheckInterval);
}
if (success) {
Counter.w++;
} else {
Counter.f++;
}
Counter.i++;
var account = _C(exchange.GetAccount);
LogProfit(account.Balance - InitAccount.Balance, account);
}
}
Я проанализирую ваш код стратегии строка за строкой, чтобы помочь вам понять его работу в деталях.
var Counter = {
i: 0,
w: 0,
f: 0
};
Этот код инициирует объект под названием Counter, который используется для отслеживания статистической информации о торговле стратегии.
Эти атрибуты будут записываться и обновляться в процессе реализации стратегии.
var InitAccount = null;
Эта строка кода инициализирует переменную под названием InitAccount, которая будет хранить информацию об аккаунте, когда стратегия начнет выполняться.
function CancelAll() {
while (true) {
var orders = _C(exchange.GetOrders);
if (orders.length == 0) {
break;
}
for (var i = 0; i < orders.length; i++) {
exchange.CancelOrder(orders[i].Id);
}
Sleep(Interval);
}
}
Это функция под названиемCancelAll()
, его целью является отмена всех невыполненных заказов на рынке.
while (true)
Это бесконечная петля, она будет продолжать работать, пока не останется незавершенных заказов.var orders = _C(exchange.GetOrders)
: Эта строка кода использует функцию exchange.GetOrders для поиска всех ожидаемых заказов на текущем счете и хранит их в переменной заказов.if (orders.length == 0)
Если длина массива заказов равна 0, это означает, что нет никаких незавершенных заказов, и петля будет прервана (прерываться).for (var i = 0; i < orders.length; i++)
: Это петля for, которая итерационно проходит через все незавершенные заказы.exchange.CancelOrder(orders[i].Id)
: Эта строка кода использует функцию exchange.CancelOrder() для отмены каждого заказа по его идентификатору.Sleep(Interval)
: Данная строка кода устанавливает период ожидания с паузой в течение определенного периода времени (в миллисекундах), чтобы гарантировать, что операции по отмене заказов не будут слишком частыми.Эта строка кода вводит период ожидания, в течение которого происходит пауза в течение определенного периода времени (в миллисекундах), чтобы гарантировать, что операция отмены заказов не является слишком частой.
function updateStatus(msg) {
LogStatus("Number of debugging sessions:", Counter.i, "succeeded:", Counter.w, "failed:", Counter.f, "\n" + msg + "#0000ff\n" + new Date());
}
Это функция под названиемupdateStatus(msg)
, который используется для обновления и записи информации о состоянии транзакции. Он принимает параметр msg, который обычно содержит информацию о текущем состоянии рынка. Конкретные операции функции включают:
ИспользованиеLogStatus()
Функция для записи информации, отображаемой в строке состояния во время выполнения стратегии.
Вmsg
параметр, который содержит информацию о текущем состоянии рынка.
Текущая дата (new Date()
) для отображения информации о времени.
Целью этой функции является запись и обновление информации о состоянии транзакции для мониторинга и анализа во время выполнения стратегии.
function main() {
if (DisableLog) {
EnableLog(false);
}
CancelAll();
InitAccount = _C(exchange.GetAccount);
Log(InitAccount);
var i = 0;
var locks = 0;
while (true) {
Sleep(Interval);
var depth = _C(exchange.GetDepth);
if (depth.Asks.length === 0 || depth.Bids.length === 0) {
continue;
}
updateStatus("Searching within the elephant... Buy one: " + depth.Bids[0].Price + ", Sell one:" + depth.Asks[0].Price + ", Lock times: " + locks);
var askPrice = 0;
for (i = 0; i < depth.Asks.length; i++) {
if (depth.Asks[i].Amount >= Lot) {
askPrice = depth.Asks[i].Price;
break;
}
}
if (askPrice === 0) {
continue;
}
var elephant = null;
// skip Bids[0]
for (i = 1; i < depth.Bids.length; i++) {
if ((askPrice - depth.Bids[i].Price) > ElephantSpace) {
break;
}
if (depth.Bids[i].Amount >= ElephantAmount) {
elephant = depth.Bids[i];
break;
}
}
if (!elephant) {
locks = 0;
continue;
}
locks++;
if (locks < LockCount) {
continue;
}
locks = 0;
updateStatus("Debug the elephant... The elephant is in gear " + i + ", " + JSON.stringify(elephant));
exchange.Buy(elephant.Price + PennyTick, Lot, "Bids[" + i + "]", elephant);
var ts = new Date().getTime();
while (true) {
Sleep(CheckInterval);
var orders = _C(exchange.GetOrders);
if (orders.length == 0) {
break;
}
if ((new Date().getTime() - ts) > WaitInterval) {
for (var i = 0; i < orders.length; i++) {
exchange.CancelOrder(orders[i].Id);
}
}
}
var account = _C(exchange.GetAccount);
var opAmount = _N(account.Stocks - InitAccount.Stocks);
if (opAmount < 0.001) {
Counter.f++;
Counter.i++;
continue;
}
updateStatus("Successful payment: " + opAmount +", Start taking action...");
exchange.Sell(elephant.Price + (PennyTick * ProfitTick), opAmount);
var success = true;
while (true) {
var depth = _C(exchange.GetDepth);
if (depth.Bids.length > 0 && depth.Bids[0].Price <= (elephant.Price-(STTick*PennyTick))) {
success = false;
updateStatus("Didn't get it, start to stop loss, currently buying one: " + depth.Bids[0].Price);
CancelAll();
account = _C(exchange.GetAccount);
var opAmount = _N(account.Stocks - InitAccount.Stocks);
if (opAmount < 0.001) {
break;
}
exchange.Sell(depth.Bids[0].Price, opAmount);
}
var orders = _C(exchange.GetOrders);
if (orders.length === 0) {
break;
}
Sleep(CheckInterval);
}
if (success) {
Counter.w++;
} else {
Counter.f++;
}
Counter.i++;
var account = _C(exchange.GetAccount);
LogProfit(account.Balance - InitAccount.Balance, account);
}
}
Это основная функция исполненияmain()
Давайте объясним его действия строку за строкой:
if (DisableLog)
: Эта строка кода проверяет, является ли переменная DisableLog истинной, и если это так, она отключит запись журнала. Это для того, чтобы гарантировать, что стратегия не записывает ненужные журналы.
CancelAll()
: Вызовите ранее объясненную функцию CancelAll(, чтобы убедиться, что нет незавершенных заказов.
InitAccount = _C(exchange.GetAccount)
: Эта строка кода извлекает информацию о текущем счете и сохраняет ее в переменной InitAccount.
var i = 0;
иvar locks = 0;
: Инициализировать две переменные, i и замки, которые будут использоваться в последующей логике стратегии.
while (true)
: Это бесконечная петля, в основном используемая для непрерывного выполнения стратегий.
Далее мы объясним основную стратегическую логику в рамкахwhile (true)
Кружка за кружкой.
while (true) {
Sleep(Interval);
var depth = _C(exchange.GetDepth);
if (depth.Asks.length === 0 || depth.Bids.length === 0) {
continue;
}
updateStatus("Searching within the elephant... Buy one: " + depth.Bids[0].Price + ", Sell one:" + depth.Asks[0].Price + ", Lock times: " + locks);
Sleep(Interval)
: Эта строка кода позволяет стратегии спать в течение определенного периода времени, чтобы контролировать частоту выполнения стратегии. Параметр Interval определяет интервал сна (в миллисекундах).
var depth = _C(exchange.GetDepth)
: Получить текущую информацию о глубине рынка, включая цены и объемы ордеров продажи и ордеров покупки.
if (depth.Asks.length === 0 || depth.Bids.length === 0)
: Эта строка кода проверяет информацию о глубине рынка, гарантируя, что существуют как ордера продажи, так и ордера покупки. Если один из них не существует, это указывает на то, что на рынке может не хватить торговой информации, поэтому стратегия будет продолжать ждать.
updateStatus("Searching within the elephant... Buy one: " + depth.Bids[0].Price + ", Sell one:" + depth.Asks[0].Price + ", Lock times: " + locks)
: Эта строка кода вызывает функцию updateStatus для обновления информации о состоянии стратегии. Она записывает текущее состояние рынка, включая самую высокую цену заказа, самую низкую цену заказа и ранее закрытые сроки (замки).
var askPrice = 0;
for (i = 0; i < depth.Asks.length; i++) {
if (depth.Asks[i].Amount >= Lot) {
askPrice = depth.Asks[i].Price;
break;
}
}
if (askPrice === 0) {
continue;
}
var elephant = null;
var askPrice = 0;
: инициализировать переменную askPrice, она будет использоваться для хранения цены ордеров продажи, которые отвечают условиям.
for (i = 0; i < depth.Asks.length; i++)
: Это цикл, используемый для прохождения информации о цене и количестве ордеров на продажу на рынке.
if (depth.Asks[i].Amount >= Lot)
: В петле проверьте, больше ли количество каждого ордера на продажу или равно указанному лоту (ручное подсчет).
if (askPrice === 0)
: Если не найдены заказы на продажу, отвечающие условиям (стоимость запроса по-прежнему 0), стратегия будет продолжать ждать и пропустить последующие операции.
var elephant = null;
: инициализируйте переменную elephant, она будет использоваться для хранения информации о заказе покупки, идентифицированной как
for (i = 1; i < depth.Bids.length; i++) {
if ((askPrice - depth.Bids[i].Price) > ElephantSpace) {
break;
}
if (depth.Bids[i].Amount >= ElephantAmount) {
elephant = depth.Bids[i];
break;
}
}
if (!elephant) {
locks = 0;
continue;
}
locks++;
if (locks < LockCount) {
continue;
}
locks = 0;
Продолжать просматривать информацию о цене и количестве ордеров на покупку на рынке, пропустив первый ордер на покупку (оферты[0]).
if ((askPrice - depth.Bids[i].Price) > ElephantSpace)
: Проверьте, больше ли разрыв между текущей ценой предложения и askPrice, чем ElephantSpace. Если да, это указывает на то, что он достаточно далеко от
if (depth.Bids[i].Amount >= ElephantAmount)
: Проверьте, является ли количество текущего ордера на покупку больше или равно ElephantAmount. Если да, сохраните информацию о заказе на покупку в переменной elephant.
if (!elephant)
: Если
locks++
Если
if (locks < LockCount)
: Проверьте, соответствовало ли количество времени блокировки требованиям (LockCount).
updateStatus("Debug the elephant... The elephant is in gear " + i + ", " + JSON.stringify(elephant));
exchange.Buy(elephant.Price + PennyTick, Lot, "Bids[" + i + "]", elephant);
var ts = new Date().getTime();
while (true) {
Sleep(CheckInterval);
var orders = _C(exchange.GetOrders);
if (orders.length == 0) {
break;
}
if ((new Date().getTime() - ts) > WaitInterval) {
for (var i = 0; i < orders.length; i++) {
exchange.CancelOrder(orders[i].Id);
}
}
}
updateStatus("Debug the elephant... The elephant is in gear " + i + ", " + JSON.stringify(elephant))
: Вызвать функцию updateStatus, чтобы записать текущее состояние стратегии, включая положение передачи найденного
exchange.Buy(elephant.Price + PennyTick, Lot, "Bids[" + i + "]", elephant)
: Используйте функцию exchange.Buy для покупки найденного
var ts = new Date().getTime()
: Получить часовую метку текущего времени для последующего расчета временных интервалов.
while (true)
: Введите новую бесконечную петлю, используемую для ожидания исполнения ордеров на покупку.
Sleep(CheckInterval)
: Стратегия спит на некоторое время, чтобы контролировать частоту проверки статуса заказа.
var orders = _C(exchange.GetOrders)
: Получить всю информацию о заказе текущего счета.
if (orders.length == 0)
: Проверьте, есть ли какие-либо незавершенные заказы, если нет, разорвать петлю.
(new Date().getTime() - ts) > WaitInterval
: Вычислить интервал времени между текущим временем и временем покупки
for (var i = 0; i < orders.length; i++)
Проверьте все незавершенные заказы.
exchange.CancelOrder(orders[i].Id)
: Используйте функцию exchange.CancelOrder для отмены каждого незавершенного заказа.
var account = _C(exchange.GetAccount);
var opAmount = _N(account.Stocks - InitAccount.Stocks);
if (opAmount < 0.001) {
Counter.f++;
Counter.i++;
continue;
}
updateStatus("Successful payment: " + opAmount + ", Start taking action...");
exchange.Sell(elephant.Price + (PennyTick * ProfitTick), opAmount);
var success = true;
while (true) {
var depth = _C(exchange.GetDepth);
if (depth.Bids.length > 0 && depth.Bids[0].Price <= (elephant.Price - (STTick * PennyTick))) {
success = false;
updateStatus("Didn't get it, start to stop loss, currently buying one: " + depth.Bids[0].Price);
CancelAll();
account = _C(exchange.GetAccount);
var opAmount = _N(account.Stocks - InitAccount.Stocks);
if (opAmount < 0.001) {
break;
}
exchange.Sell(depth.Bids[0].Price, opAmount);
}
var orders = _C(exchange.GetOrders);
if (orders.length === 0) {
break;
}
Sleep(CheckInterval);
}
if (success) {
Counter.w++;
} else {
Counter.f++;
}
Counter.i++;
var account = _C(exchange.GetAccount);
LogProfit(account.Balance - InitAccount.Balance, account);
}
var account = _C(exchange.GetAccount)
: Получить информацию о текущем счете.
var opAmount = _N(account.Stocks - InitAccount.Stocks)
Если изменение меньше 0,001, это означает, что покупка не удалась, увеличить количество неудач и продолжить следующую петлю.
updateStatus("Successful payment: " + opAmount + ", Start taking action...")
: Записывать информацию о успешной покупке
exchange.Sell(elephant.Price + (PennyTick * ProfitTick), opAmount)
: Используйте функцию exchange.Sell для продажи успешно купленного
Введите новую бесконечную петлю, используемую для ожидания исполнения ордеров продажи.
var depth = _C(exchange.GetDepth)
: Получить глубокую информацию о рынке.
if (depth.Bids.length > 0 && depth.Bids[0].Price <= (elephant.Price - (STTick * PennyTick)))
: Проверьте информацию о глубине рынка, если рыночная цена уже упала до уровня стоп-лосса, затем выполните операцию стоп-лосса.
CancelAll()
: Вызвать функцию CancelAll(, чтобы отменить все незавершенные заказы, чтобы избежать риска позиции.
if (opAmount < 0.001)
: Проверьте количество покупки снова, если оно меньше 0,001, это означает, что покупка не удалась, выйти из цикла.
exchange.Sell(depth.Bids[0].Price, opAmount)
Выполните операцию стоп-лосса, продавайте оставшиеся активы по самой низкой цене на текущем рынке.
Наконец, обновить количество успешных и неудачных сделок на основе того, была ли сделка успешной или нет, и записать прибыль от торговли.
Основная идея этой стратегии заключается в том, чтобы найти слонов (большие заказы на покупку) на рынке, купить и продать их, чтобы получить небольшую прибыль.
В целом, эта стратегия является высокочастотной торговой стратегией, направленной на использование глубинной информации о рынке для выявления больших заказов на покупку и проведения операций по покупке и продаже в короткий период времени.
Обратите внимание, что стратегия основана на конкретных рынках и торговых платформах. Для разных рынков и бирж могут потребоваться соответствующие корректировки и оптимизации. В практическом применении инвесторам необходимо тщательно протестировать и оценивать эффективность стратегии, чтобы убедиться, что она соответствует их инвестиционным целям и толерантности к риску.
По мере продолжения выполнения стратегии он будет выполнять следующие операции:
Во-первых, стратегия будет проверять глубокую информацию о рынке, чтобы понять текущую ситуацию с ордерами продажи и покупки.
Далее стратегия будет пытаться найти ордера на продажу, которые соответствуют критериям, в частности, ордера на продажу с количеством, большим или равным лоту.
Затем стратегия будет продолжать поиск слонов (большое количество заказов на покупку). Она будет пересекать рынок, пропуская первый (обычно самый дорогой заказ на покупку). Если она найдет слона, который соответствует критериям, она будет записывать информацию о слоне и увеличивать блокировки.
Если последовательно обнаружено достаточное количество слонов (контролируется параметром LockCount), стратегия будет выполнять следующие операции:
Вся стратегия постоянно выполняет вышеуказанные операции, чтобы поймать как можно больше слонов и получить небольшую прибыль. Это высокочастотная торговая стратегия, которая требует быстрых ответов на изменения рынка, а также учитывает управление рисками и механизмы остановки потерь для защиты капитала. Инвесторы должны тщательно рассмотреть возможность использования этой стратегии, особенно на сильно волатильных рынках.
Стратегия Penny Jump является типичным примером высокочастотного трейдинга, демонстрирующим тонкую игру и конкуренцию между участниками рынка. Эта стратегия особенно заметна на рынке криптовалют из-за его больших колебаний, где институциональные инвесторы и трейдеры с высокой частотой все стремятся к быстрой прибыли. Однако это также делает рынок полным проблем, требуя постоянной адаптации и корректировки стратегий для поддержания конкурентных преимуществ.