前回の記事では,クロス・エクスチェンジ
次の通りです公共のコードの簡素化このオリジナルの戦略のコード原則は非常にシンプルで,かつては非常に収益性がありました.現在は利用できません. 参照のみです.
この戦略は,オード価格,オード価格,待機中のオードボリュームなど,異なる取引所からのオーダーブックデータをほぼ同期的に取得する.次に,市場動態を推論するために,異なる取引所の中間価格 (すなわちオード価格とオード価格の平均値) を比較する.
この戦略は主に3つの外部取引所の価格変動 (okex,binance,huobipro) に焦点を当てています.
ここでは,それぞれのトレンドXは,特定の
この戦略は,トレンドが確認された後にのみ購入または販売し,各オーダーを出す前に前のオーダーをキャンセルする (つまり,リスク蓄積につながる偶然の未定オーダーを避ける).同時に,スクリプトはレバレッジ,バッチ運用,リスク管理モニタリングなどのモジュールも設定する.これは,複数のアカウントと複数の通貨ペアがライブ取引で同時に使用され,それによって戦略の"取引頻度"と"資本利用効率"を拡大することを意味します.
また,この戦略は高周波戦略です.各オーダーの利益または損失に注意する必要はありません.また,損失を停止する必要もありません.利益を得る可能性がある限り続けることができます.
// Hyperparameter settings
const SYMBOL = "BTC_USDT"; // Trading pair
const PRICE_INCREMENT = 0.1; // Price increment
const LEVEL = 10; // Sensitivity of trend judgment
const RATIO = 10; // Order price adjustment ratio
const INTERVAL = 200; // Time interval (milliseconds)
const S_AMOUNT = 0.02; // Default transaction volume
const MIN_AMOUNT = 0.005; // Minimum transaction volume
// Initial state
let buyOrders = [];
let sellOrders = [];
let previousPrices = [0, 0, 0]; // Store the previous price
let loop = 0;
// Get order book data
function fetchOrderBooks() {
let orderBooks = [];
let tasks = [];
// Start asynchronous order book acquisition tasks for all exchanges
for (let i = 0; i < exchanges.length; i++) {
// Assume that each exchange object can call the Go method
let task = exchanges[i].Go("GetDepth");
tasks.push({ index: i, task: task });
}
// Wait for all tasks to complete and collect results
for (let i = 0; i < tasks.length; i++) {
let { index, task } = tasks[i];
try {
// Waiting for an asynchronous task to return a result
let depth = task.wait(1000);
// Check if the returned data is valid
if (!depth || !depth.Bids || !depth.Asks) {
throw new Error("The returned order book data is invalid");
}
// Add valid order book data to the result array
orderBooks[index] = depth;
} catch (error) {
// Recording error logs
Log(`Failed to obtain the order book of exchange ${index}: ${error.message}`);
// Added default order book data to avoid crashes
orderBooks[index] = {
Bids: [[0, 0]],
Asks: [[0, 0]]
};
}
}
return orderBooks;
}
// Judge the trends
function calculateTrend(orderBooks) {
let trends = [];
for (let i = 0; i < orderBooks.length; i++) {
const midPrice = (orderBooks[i].Bids[0][0] + orderBooks[i].Asks[0][0]) / 2;
if (midPrice > previousPrices[i] + LEVEL * PRICE_INCREMENT) {
trends.push(1); // Upward trend
} else if (midPrice < previousPrices[i] - LEVEL * PRICE_INCREMENT) {
trends.push(-1); // Downward trend
} else {
trends.push(0); // No significant trend
}
previousPrices[i] = midPrice; // Update price record
}
return trends.reduce((a, b) => a + b, 0); // Return to overall trend
}
// Cancel all pending orders
function cancelOrders(orders) {
for (let orderId of orders) {
try {
exchanges[0].CancelOrder(orderId); // Use the main exchange by default
Log(`Cancel order: ${orderId}`);
} catch (error) {
Log(`Failed to cancel order: ${error.message}`);
}
}
}
// Create a buy order
function createBuyOrder(price, amount) {
try {
const orderId = exchanges[0].Buy(price, amount);
buyOrders.push(orderId);
Log(`Create a buy order: price ${price}, quantity ${amount}`);
} catch (error) {
Log(`Failed to create buy order: ${error.message}`);
}
}
// Create a sell order
function createSellOrder(price, amount) {
try {
const orderId = exchanges[0].Sell(price, amount);
sellOrders.push(orderId);
Log(`Create a sell order: price ${price}, quantity ${amount}`);
} catch (error) {
Log(`Failed to create sell order: ${error.message}`);
}
}
function main() {
while (true) {
try {
// Get order book data
const orderBooks = fetchOrderBooks();
// Calculate trends
const trend = calculateTrend(orderBooks);
Log(`Current trend: ${trend}`);
// Cancel pending order
cancelOrders(buyOrders);
cancelOrders(sellOrders);
buyOrders = [];
sellOrders = [];
// Order based on trends
if (trend > 0 && loop > 0) {
const price = _N(orderBooks[0].Bids[0][0] + RATIO * PRICE_INCREMENT, 2);
const amount = _N(Math.max(S_AMOUNT, MIN_AMOUNT), 4);
createBuyOrder(price, amount);
} else if (trend < 0 && loop > 0) {
const price = _N(orderBooks[0].Asks[0][0] - RATIO * PRICE_INCREMENT, 2);
const amount = _N(Math.max(S_AMOUNT, MIN_AMOUNT), 4);
createSellOrder(price, amount);
}
// Loop count and interval
loop++;
Sleep(INTERVAL);
} catch (error) {
Log(`Main logic error: ${error.message}`);
}
}
}
市場が効率化される
より多くの定量または高頻度戦略が関与し,同じリード-ラグ関係を発見すると,大量の資金が価格差を迅速に排除する.市場はますます"同期化"になり,戦略が小さな価格差から"リスクフリー"アービタージまたは短期アービタージを行うのは困難である.
換算制限や料金変更
異なる取引所の手数料構造が変化するにつれて,手数料コストが仲介利益を超えると,高周波取引戦略の収益性は大幅に低下する.または,取引所はマッチング速度を加速し,頻度と量を制限し,遅延を減らす場合,それはもともと一貫性のない遅延に依存した戦略を無効にする.
流動性の衰退と滑り
市場規模が不十分である場合,高周波戦略はしばしばより深刻なスライプに直面する.または,大きな注文が価格を急速に押し上げ,当初予想されていた低価格で高価格で販売する価格が,自社の注文に影響を受け,収益が低下する.
市場の変動の変化
ある戦略は"高波動性"または"特定の期間"で非常にうまく機能します.市場が平坦または波動性が低下し,レバレッジが減少すると,戦略は適した環境を失い,頻繁に損失を伴う可能性があります.
高周波取引戦略の鍵は,複数の取引所からの価格の把握と"トレンドシンセシス"の判断にある.リードラグ原理に基づく超高周波,高速なエントリー&エグジット取引方法を実現した.どの取引所の価格が最初に動いているかを観察し,次に他の取引所の価格を追跡させ,即時的な価格差または短期的なトレンドを把握する.しかし,著者が述べたように,市場の環境の変化,戦略の均質性,処理手数料および周波数制限により,この戦略は徐々に有用性が低下し,収益性さえ失う.このタイプのリードラグ戦略を再開したい人は,最新の市場手数料構造 (流動性,マッチングアルゴリズム,速度管理) と組み合わせて取引モジュールを最適化し,変化する市場環境の中で競争力を維持するために,リスク管理の速度に注意を払う必要があります.