Algoritmik Treydingda Order Turlari: Chasing bilan Limitdan Virtual Orderlargacha
Yangi boshlovchi birja terminalini ochganda, ikkita tugmani ko'radi: "Sotib olish" va "Sotish". Algo-treyder o'z kodini ochganda esa, yigirma yettita order turini, uchta abstraksiya darajasini va noutbukni yopib, bozorda bodring sotgisi keladigan bir dasta chekka holatlarni ko'radi. Ammo bodringlar, afsuski, sizga 3:59 UTC da funding stavkasi arbitraji o'tkazishga imkon bermaydi — shuning uchun mavzuga o'tamiz.
Ushbu maqolada biz oddiy birja orderlaridan tortib, faqat sizning tizimingiz ichida mavjud bo'lgan va hech qachon order kitobida ko'rinmaydigan sintetik virtual konstruksiyalargacha bo'lgan butun yo'lni bosib o'tamiz. TypeScript, Python, biroz og'riq va bir oz ma'rifat kutmoqda.
1. Standart Birja Orderlari: O'tkazib Yuborib Bo'lmaydigan Asos
Standart order turlarining tasnifi: marketdan icebergga qadar
Murakkab narsa qurishdan oldin, asosiy qurilish bloklarini to'g'ri tushunganimizga ishonch hosil qilishimiz kerak. Qancha odam stop-limit va stop-marketni chalkashtirib yuborishi va keyin nega o'z stopi "ishlamaganini" ajablanishi hайratlanarli (spoyler: u ishlagan, lekin limit order sirpanish (slippage) tufayli bajarilmagan).
Market order
Eng oddiy va shu bilan birga eng xavfli tur. Siz birjaga aytasiz: "hozir, mavjud bo'lgan har qanday narxda sotib ol/sot." Birja order kitobidan likvidlikni eng yaxshi narxdan boshlab oladi. Agar eng yaxshi darajadagi hajm yetarli bo'lmasa — u yanada pastroqqa siljiydi.
Qachon ishlatish kerak: shoshilinch pozitsiyadan chiqish, tezlik narxdan muhimroq bo'lgan signalni bajarish.
Xavflar: yupqa bozorda 100 BTC uchun market order narxni bir necha foizga siljitishi mumkin. Ta'sirni hisobga olmasdan market orderlarni modellashtiruvchi backtestlar sof xayoldir.
Limit order
Siz aniq narxni ko'rsatasiz. Order order kitobiga kiradi va kimdir sizning narxingizga rozi bo'lguncha kutadi. Agar limit-bid orderning narxi joriy bozordan yuqori bo'lsa — u darhol bajariladi (market order kabi, lekin kafolatlangan maksimal narx bilan).
Muhim jihat: limit order bajarilishini kafolatlamaydi. Narx sizning darajangizga yetib, orqaga qaytishi mumkin, sizni navbatda qoldirib (navbat pozitsiyasi haqidagi maqolamizda batafsilroq).
Stop-market va Stop-limit
Aynan shu yerda chalkashlik boshlanadi. Ikkala tur ham trigger narxi (stop price) yetganda faollashadigan "uxlab yotgan" orderlar hisoblanadi. Ammo:
- Stop-market: ishga tushganda market orderga aylanadi. Bajarilishni kafolatlaydi, lekin narxni emas.
- Stop-limit: ishga tushganda limit orderga aylanadi. Narxni kafolatlaydi (ko'rsatilganidan yomonroq bo'lmaydi), lekin bajarilishni emas.
O'zgaruvchan kripto bozorida stop-limit "o'tkazib yuborishi" mumkin — narx stopni yorib o'tdi, limit order joylashtirildi, lekin bozor allaqachon uchib o'tdi. Sizda bajarilmagan limit order va o'sib borayotgan zarar qoladi. Aynan shuning uchun stop-loss uchun ko'proq stop-market ishlatiladi.
Trailing stop
Narxni belgilangan masofada "kuzatib boruvchi" stop. Narx ko'tariladi — stop ham yuqoriga siljiydi. Narx tushadi — stop joyida qoladi. Trend bo'yicha strategiyalarda foydani himoya qilish uchun foydali.
Birja qo'llab-quvvatlashi: hamma birjalar ham tabiiy trailing stopni qo'llab-quvvatlamaydi. Algo-treyderlar ko'pincha ularni dasturiy tarzda amalga oshiradi — bu parametrlar ustidan ko'proq nazorat beradi (callback rate, faollashtirish narxi, qadam o'lchami).
Iceberg order
Umumiy hajmning faqat bir qismi order kitobida ko'rinadigan order. Siz 1000 BTC sotib olmoqchisiz, lekin kitobda faqat 10 tasini ko'rsatasiz. Birinchi 10 tasi bajarilganda — keyingi 10 tasi paydo bo'ladi.
Nima uchun: haqiqiy niyatlaringizni bozordan yashirish uchun. Kitobdagi katta order hammaga "kimdir katta miqdorda sotib olmoqchi/sotmoqchi" degan signal beradi. Javobga HFT algoritmlari front-running qila boshlaydi va narx sizdan uzoqlashadi.
Eslatma: ko'plab kripto birjalarida iceberg orderlar yo qo'llab-quvvatlanmaydi, yoki bir xil hajmlar naqshi orqali oson aniqlanadi. Ilg'or algoritmlar ko'rinadigan qism hajmini tasodifiylashtiradi.
Time-in-force parametrlari: GTC, GTD, IOC, FOK
Bular alohida order turlari emas, balki time-in-force parametrlari — order qancha vaqt yashaydi:
| Parametr | To'liq nomi | Xatti-harakati |
|---|---|---|
| GTC | Good Till Cancelled | Bekor qilinguncha yashaydi. Standart default |
| GTD | Good Till Date | Belgilangan sana/vaqtgacha yashaydi |
| IOC | Immediate or Cancel | Darhol bajariladi (to'liq yoki qisman), qolgani bekor qilinadi |
| FOK | Fill or Kill | Faqat to'liq va darhol bajariladi. Iloji bo'lmasa — butunlay bekor qilinadi |
IOC va FOK farqi: farq muhim. IOC qisman bajarilishi mumkin — siz 100 BTC sotib olmoqchi edingiz, 3 tasini sotib oldingiz, qolgani bekor qilindi. FOK esa yo hammasi, yo hech narsa.
Post-only (Faqat Maker)
Order kitobiga maker sifatida kiritilishi kafolatlangan va hech qachon taker sifatida bajarilmaydigan order. Agar joylashtirish paytida narx darhol bajarilishga olib kelsa — birja uni rad etadi (yoki narxni tuzatadi, birjaga qarab).
Nima uchun: maker komissiyalari odatda taker komissiyalaridan past (Binanceda — VIP darajalar uchun 0,02% va 0,04%). Kuniga minglab order joylashtiradigan market meyker uchun komissiya farqi foyda va zarar orasidagi farqdir.
2. TWAP va VWAP: Institutsiyalar Order Kitobida Filni Qanday Yashiradi
Хеdж-fond 50 million dollarlik pozitsiya sotib olmoqchi bo'lganda, u bitta market order joylashtirmaydi. U bajarish algoritmlaridan foydalanadi — katta orderni ko'plab kichikroq qismlarga bo'lib, ularni vaqt davomida bajaradigan va bozorga ta'sirni minimallashtiradigan algoritmlar.
TWAP (Time-Weighted Average Price)
G'oya juda oddiy: umumiy hajmni teng qismlarga bo'lish va teng vaqt oralig'ida bajarish.
import asyncio
from datetime import datetime, timedelta
class TWAPExecutor:
"""
TWAP executor: splits a large order into equal parts
and executes them at equal time intervals.
"""
def __init__(self, exchange, symbol: str, side: str,
total_qty: float, duration_minutes: int, num_slices: int):
self.exchange = exchange
self.symbol = symbol
self.side = side
self.total_qty = total_qty
self.slice_qty = total_qty / num_slices
self.interval = (duration_minutes * 60) / num_slices
self.num_slices = num_slices
self.executed_qty = 0.0
self.fills: list[dict] = []
async def execute(self):
for i in range(self.num_slices):
remaining = self.total_qty - self.executed_qty
qty = min(self.slice_qty, remaining)
if qty <= 0:
break
try:
order = await self.exchange.create_order(
symbol=self.symbol,
type="market",
side=self.side,
amount=qty,
)
self.executed_qty += float(order["filled"])
self.fills.append(order)
print(f"[TWAP] slice {i+1}/{self.num_slices}: "
f"filled {order['filled']} @ {order['average']}")
except Exception as e:
print(f"[TWAP] slice {i+1} failed: {e}")
if i < self.num_slices - 1:
await asyncio.sleep(self.interval)
avg_price = (
sum(f["cost"] for f in self.fills) /
sum(f["filled"] for f in self.fills)
) if self.fills else 0
print(f"[TWAP] done: {self.executed_qty}/{self.total_qty} "
f"avg price: {avg_price:.2f}")
VWAP (Volume-Weighted Average Price)
VWAP aqlliroq: u odatiy savdo hajmi profilini hisobga oladi. Agar kunlik hajmning 30% odatda 9:00 dan 10:00 gacha savdo qilinsa, VWAP order hajmining 30% ini o'sha oynada bajaradi. Maqsad — o'rtacha bajarilish narxini bozor VWAP-iga imkon qadar yaqinlashtirish.
class VWAPExecutor:
"""
VWAP executor: distributes volume proportionally
to the historical volume profile.
"""
def __init__(self, exchange, symbol: str, side: str,
total_qty: float, volume_profile: list[float]):
self.exchange = exchange
self.symbol = symbol
self.side = side
self.total_qty = total_qty
total_weight = sum(volume_profile)
self.weights = [w / total_weight for w in volume_profile]
async def execute(self, interval_seconds: float = 60.0):
executed = 0.0
for i, weight in enumerate(self.weights):
qty = self.total_qty * weight
remaining = self.total_qty - executed
qty = min(qty, remaining)
if qty <= 0:
break
order = await self.exchange.create_order(
symbol=self.symbol,
type="market",
side=self.side,
amount=qty,
)
executed += float(order["filled"])
print(f"[VWAP] period {i+1}: weight={weight:.2%}, "
f"filled={order['filled']} @ {order['average']}")
await asyncio.sleep(interval_seconds)
TWAP va VWAP farqi: TWAP soddaroq va bashorat qilish osonroq. VWAP yaxshiroq o'rtacha narx beradi, lekin ishonchli hajm profilini talab qiladi. Hajmlar wash-trade qilinishi mumkin bo'lgan kripto bozorida VWAP profilini ehtiyotkorlik bilan qurish kerak.
3. Chasing bilan Limit: Orderingiz Narxni Quvishni Bilganda
Chasing limit: order sozlanadigan tajovuzkorlik bilan harakatlanuvchi narxni quvadi
Endi ish qiziqarli bo'la boshlaydi. Standart limit order passiv obyekt: u order kitobida o'tirib kutadi. Narx harakatlansa — order bajarilmay qoladi. Algo-treyder uchun bu ko'pincha maqbul emas: kirish signali ishga tushdi, lekin bozor 0,1% harakatlangani sababli pozitsiya qurilmadi.
Chasing limit order — bu limit order atrofidagi dasturiy o'ram bo'lib, u:
- Joriy eng yaxshi narxda (yoki kichik offset bilan) limit order joylashtiradi
- Narxni WebSocket orqali kuzatib boradi
- Agar narx orderdan uzoqlashsa — uni bekor qilib, joriy narxga yaqinroq qayta joylashtiradi
- Order bajarilguncha yoki ruxsat etilgan chetlanishdan oshguncha takrorlaydi
Asosiy Parametrlar
- chase_interval_ms — orderni qanchalik tez-tez tekshirish va qayta joylashtirish. 100ms — tajovuzkor, 1000ms — bo'shashgan.
- max_chase_distance — order bekor qilinishidan oldin dastlabki narxdan maksimal chetlanish. Qochib ketayotgan bozorni quvishdan himoya.
- aggression_level — limit orderni bozor narxiga qanchalik yaqin joylashtirish kerak.
0— eng yaxshi bid/askda (passiv),1— spredni kesib o'tish (tajovuzkor, aslida taker). - chase_on_partial — order qisman bajarilganda quvishni davom ettirish kerakmi.
TypeScript Implementatsiyasi
interface ChasingOrderParams {
symbol: string;
side: "buy" | "sell";
totalQty: number;
/** 0 = passive (at best bid/ask), 1 = cross spread */
aggression: number;
/** max price deviation from initial price */
maxChaseDistance: number;
/** how often to re-evaluate, ms */
chaseIntervalMs: number;
/** stop chasing after this many ms */
timeoutMs: number;
}
class ChasingLimitOrder {
private currentOrderId: string | null = null;
private filledQty = 0;
private initialPrice: number | null = null;
private startTime = Date.now();
constructor(
private exchange: any, // ccxt exchange instance
private params: ChasingOrderParams
) {}
async execute(): Promise<{ filledQty: number; avgPrice: number }> {
const fills: Array<{ qty: number; price: number }> = [];
while (this.filledQty < this.params.totalQty) {
// Timeout
if (Date.now() - this.startTime > this.params.timeoutMs) {
console.log("[CHASE] timeout reached, cancelling");
await this.cancelCurrent();
break;
}
// Get current order book
const book = await this.exchange.fetchOrderBook(
this.params.symbol, 5
);
const bestBid = book.bids[0][0];
const bestAsk = book.asks[0][0];
const spread = bestAsk - bestBid;
// Calculate target price
let targetPrice: number;
if (this.params.side === "buy") {
targetPrice = bestBid + spread * this.params.aggression;
} else {
targetPrice = bestAsk - spread * this.params.aggression;
}
// Remember the initial price
if (this.initialPrice === null) {
this.initialPrice = targetPrice;
}
// Check max chase distance
const deviation = Math.abs(targetPrice - this.initialPrice);
if (deviation > this.params.maxChaseDistance) {
console.log(
`[CHASE] max deviation exceeded: ${deviation.toFixed(4)} > ` +
`${this.params.maxChaseDistance}`
);
await this.cancelCurrent();
break;
}
// Check current order
if (this.currentOrderId) {
const order = await this.exchange.fetchOrder(
this.currentOrderId, this.params.symbol
);
if (order.status === "closed") {
fills.push({ qty: order.filled, price: order.average });
this.filledQty += order.filled;
this.currentOrderId = null;
continue;
}
// Update filledQty for partial fills
if (order.filled > 0) {
const newFilled = order.filled - (
fills.reduce((s, f) => s + f.qty, 0) - this.filledQty
);
// Order is in place — do we need to reprice?
}
const currentPrice = parseFloat(order.price);
const priceDiff = Math.abs(currentPrice - targetPrice);
const tickSize = spread * 0.1 || 0.01;
if (priceDiff > tickSize) {
// Price moved — reprice
console.log(
`[CHASE] repricing: ${currentPrice} -> ` +
`${targetPrice.toFixed(4)}`
);
await this.cancelCurrent();
} else {
// Order is at the right price — wait
await this.sleep(this.params.chaseIntervalMs);
continue;
}
}
// Place new order
const remainingQty = this.params.totalQty - this.filledQty;
const order = await this.exchange.createLimitOrder(
this.params.symbol,
this.params.side,
remainingQty,
targetPrice
);
this.currentOrderId = order.id;
console.log(
`[CHASE] placed ${this.params.side} ${remainingQty} ` +
`@ ${targetPrice.toFixed(4)}`
);
await this.sleep(this.params.chaseIntervalMs);
}
const totalCost = fills.reduce((s, f) => s + f.qty * f.price, 0);
const avgPrice = this.filledQty > 0 ? totalCost / this.filledQty : 0;
return { filledQty: this.filledQty, avgPrice };
}
private async cancelCurrent(): Promise<void> {
if (this.currentOrderId) {
try {
await this.exchange.cancelOrder(
this.currentOrderId, this.params.symbol
);
} catch { /* order already filled or cancelled */ }
this.currentOrderId = null;
}
}
private sleep(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}
}
Chasing Zarar Keltiradigan Holatlar
Chasing kuchli vosita, lekin uni zarar generatoriga aylantirish oson:
- Cancel/replace spami. Har bir bekor qilish va qayta joylashtirish API uchun yuk hisoblanadi. Birjalar so'rovlarni cheklaydi (rate limit), va tajovuzkor chasing API kalitingiz bloklanishiga olib kelishi mumkin.
- Noqulay tanlov (adverse selection). Agar narx sizdan qochayotgan bo'lsa — bozor siz bilmagan narsani bilishi mumkin. Bunday holatda narxni quvish tepada sotib olishni anglatadi.
- Maker'dan Taker'ga o'tish. Yuqori tajovuzkorlik bilan siz aslida taker komissiyalarini to'laysiz, lekin kechikish bilan (bekor qilish + yangi order). Ba'zan shunchaki market order joylashtirish osonroq.
4. Vaqtga Asoslangan Orderlar: Millisekund Aniqligi
Order "X narxda" emas, balki "T vaqtda" bajarilishi kerak bo'lgan holatlar mavjud. G'alati eshitiladimi? Aslida bu butun bir strategiyalar sinfi.
Foydalanish holatlari
Funding stavkasi arbitraji. Perpetual fyucherslarda funding har 8 soatda to'lanadi (00:00, 08:00, 16:00 UTC Binanceda). Agar funding stavkasi = +0,1% bo'lsa, hisob-kitob paytida short pozitsiyada bo'lishingiz kerak. Strategiya: hisob-kitobdan bir necha soniya oldin short ochish, fundingni yig'ish, pozitsiyani yopish. Vaqt aniqligi hal qiluvchi — bir soniya kechikish o'tkazib yuborilgan funding degani.
Sessiya ochilishi/yopilishi. An'anaviy bozorlarda va ba'zi kripto derivativlarda qat'iy sessiyalar mavjud. Ochilish auksioni (NYSE, CME) — bu likvidlik cho'qqisiga chiqqan payt. Auksiondan 100ms oldin order joylashtirish afzallik hisoblanadi.
Yangiliklarga asoslangan bajarish. Inflyatsiya ma'lumotlari rejalashtirilgan vaqtda e'lon qilinadi. Algoritm sonni yangiliklar oqimidan tahlil qiladi va 50ms ichida order joylashtiradi. Bu yerda vaqtga asoslangan bajarish voqealarga asoslangan mantiq bilan birlashtiriladi.
Implementatsiya
class TimeBasedOrder {
constructor(
private exchange: any,
private symbol: string,
private side: "buy" | "sell",
private qty: number,
private orderType: "market" | "limit",
private limitPrice?: number
) {}
/**
* Schedule execution at a precise time.
* Uses a busy-wait loop for maximum precision.
*/
async executeAt(targetTime: Date): Promise<any> {
const targetMs = targetTime.getTime();
// Phase 1: coarse wait (sleep)
const coarseWait = targetMs - Date.now() - 500; // wake up 500ms early
if (coarseWait > 0) {
console.log(
`[TIME-ORDER] sleeping for ${(coarseWait / 1000).toFixed(1)}s`
);
await new Promise((r) => setTimeout(r, coarseWait));
}
// Phase 2: precise wait (busy-wait)
while (Date.now() < targetMs) {
// spin — burns CPU, but achieves ~1ms precision
}
// Phase 3: execution
const sendTime = Date.now();
const order = await this.exchange.createOrder(
this.symbol,
this.orderType,
this.side,
this.qty,
this.limitPrice
);
console.log(
`[TIME-ORDER] executed at ${new Date(sendTime).toISOString()}, ` +
`target was ${targetTime.toISOString()}, ` +
`delta: ${sendTime - targetMs}ms`
);
return order;
}
}
// Example: place an order exactly at 00:00:00 UTC (funding settlement)
const executor = new TimeBasedOrder(exchange, "BTC/USDT", "sell", 0.1, "market");
const target = new Date("2026-03-24T00:00:00.000Z");
await executor.executeAt(target);
Muhim eslatma: vaqtga asoslangan orderning aniqligi sizning kodingiz bilan emas, balki birjaga tarmoq kechikishi bilan cheklanadi. Agar API'ga ping 50ms bo'lsa, mukammal busy-wait ham 50ms delta beradi. Jiddiy HFT uchun co-location ishlatiladi — server jismonan birjaning matching engine yonida joylashadi.
5. Virtual/Sintetik Orderlar: Tizimingizdagi Ko'rinmaslar
Virtual orderlar: orderlar trigger ishga tushguncha faqat bot xotirasida mavjud
Bu ehtimol algo-treyder arsenalidagi eng kam baholangan vosita. Virtual order (sintetik order deb ham ataladi) — bu faqat sizning tizimingizda mavjud bo'lgan order. U trigger sharti bajarilguncha (odatda — narx muayyan darajaga yetguncha) birjaga yuborilmaydi.
Bu Qanday Ishlaydi
- Sizning algoritmingiz qaror qiladi: "BTC ni 40 000 dollarga sotib olmoqchiman"
- Birjaga limit order yuborish o'rniga, xotirada virtual order yaratiladi
- WebSocket narx oqimiga obuna bo'ladi
- Bid/ask 40 000 dollarga yetganda — birjaga haqiqiy market yoki limit order yuboriladi
Nima Uchun Virtual Orderlar Muhim
Ma'lumot sizib chiqmaydi. Sizning orderingiz order kitobida ko'rinmaydi. Hech kim — boshqa treyderlar ham, HFT algoritmlari ham, hatto birjaning o'zi ham — bajarilish paytigacha sizning niyatlaringiz haqida bilmaydi. Bu kuchlar muvozanatini tubdan o'zgartiradi.
Front-runningdan himoya. Kripto birjalarda, ayniqsa kam shaffof bo'lganlarida, katta limit orderlar haqidagi ma'lumot front-running uchun ishlatilishi mumkinligi haqida asosli shubhalar mavjud (bu haqda tadqiqotlar ham bor). Virtual orderlar bu xavfni bartaraf etadi.
Grid botlar. Klassik grid bot turli narx darajalarida 50-200 ta order to'ridan iborat setka joylashtiradi. Agar siz ularning barchasini birjaga yuborsangiz — bu kitobda 200 ta order bo'ladi, ular: (a) hamma uchun ko'rinadi, (b) birjadagi order limitini ishlatib qo'yadi (odatda hisob uchun 200-300 ta ochiq order), (c) narx keskin harakatlansa, ularning barchasi bajarilib, sizda ulkan pozitsiya paydo bo'ladi. Virtual orderlar barcha uchta muammoni hal qiladi.
Tushayotgan pichoqlarni ushlash. Strategiya: joriy narxdan -5%, -10%, -15% pastda virtual sotib olish orderlarini joylashtirish. Bozor tushsa — orderlar asta-sekin ishga tushadi. Tushmasa — hech narsani xavf ostiga qo'ymaysiz va birja order slotlarini ishlatmaysiz.
TypeScript Implementatsiyasi
interface VirtualOrder {
id: string;
symbol: string;
side: "buy" | "sell";
triggerPrice: number;
qty: number;
/** Order type sent to the exchange upon triggering */
executionType: "market" | "limit";
/** For limit: offset from trigger price */
limitOffset?: number;
status: "pending" | "triggered" | "filled" | "failed";
}
class VirtualOrderManager {
private orders: Map<string, VirtualOrder> = new Map();
private orderCounter = 0;
constructor(private exchange: any) {}
/**
* Create a virtual order. Nothing is sent to the exchange.
*/
addOrder(params: Omit<VirtualOrder, "id" | "status">): string {
const id = `virt_${++this.orderCounter}`;
this.orders.set(id, { ...params, id, status: "pending" });
console.log(
`[VIRTUAL] created ${params.side} ${params.qty} ` +
`${params.symbol} @ trigger ${params.triggerPrice}`
);
return id;
}
/**
* Called on every price tick (from WebSocket).
*/
async onPriceUpdate(
symbol: string, bestBid: number, bestAsk: number
): Promise<void> {
for (const [id, order] of this.orders) {
if (order.symbol !== symbol || order.status !== "pending") continue;
const triggered =
(order.side === "buy" && bestAsk <= order.triggerPrice) ||
(order.side === "sell" && bestBid >= order.triggerPrice);
if (!triggered) continue;
order.status = "triggered";
console.log(
`[VIRTUAL] ${id} triggered! bid=${bestBid} ask=${bestAsk}`
);
try {
let realOrder: any;
if (order.executionType === "market") {
realOrder = await this.exchange.createMarketOrder(
order.symbol, order.side, order.qty
);
} else {
const limitPrice = order.side === "buy"
? order.triggerPrice + (order.limitOffset ?? 0)
: order.triggerPrice - (order.limitOffset ?? 0);
realOrder = await this.exchange.createLimitOrder(
order.symbol, order.side, order.qty, limitPrice
);
}
order.status = "filled";
console.log(
`[VIRTUAL] ${id} filled: ${realOrder.filled} ` +
`@ ${realOrder.average ?? realOrder.price}`
);
} catch (err) {
order.status = "failed";
console.error(`[VIRTUAL] ${id} execution failed:`, err);
}
}
}
/**
* Get all active virtual orders.
*/
getPendingOrders(): VirtualOrder[] {
return [...this.orders.values()].filter(
(o) => o.status === "pending"
);
}
cancelOrder(id: string): boolean {
const order = this.orders.get(id);
if (order && order.status === "pending") {
this.orders.delete(id);
return true;
}
return false;
}
}
// --- Example: Grid bot with virtual orders ---
async function gridBot(exchange: any) {
const manager = new VirtualOrderManager(exchange);
const currentPrice = 42000;
const gridStep = 200; // grid step
const gridLevels = 20; // levels in each direction
const qtyPerLevel = 0.01; // BTC per level
// Create virtual grid
for (let i = 1; i <= gridLevels; i++) {
// Buy orders below current price
manager.addOrder({
symbol: "BTC/USDT",
side: "buy",
triggerPrice: currentPrice - gridStep * i,
qty: qtyPerLevel,
executionType: "limit",
limitOffset: 1, // limit price = trigger + 1 USDT
});
// Sell orders above current price
manager.addOrder({
symbol: "BTC/USDT",
side: "sell",
triggerPrice: currentPrice + gridStep * i,
qty: qtyPerLevel,
executionType: "limit",
limitOffset: 1,
});
}
console.log(
`[GRID] created ${gridLevels * 2} virtual orders, ` +
`0 on exchange`
);
// WebSocket subscription (pseudocode for ccxt.pro)
while (true) {
const ticker = await exchange.watchTicker("BTC/USDT");
await manager.onPriceUpdate(
"BTC/USDT", ticker.bid, ticker.ask
);
}
}
Virtual Orderlarning Zaif Tomonlari
-
Kechikish bo'shlig'i. Siz narxni ko'rgan payt bilan haqiqiy order birjaga yetib borgan payt orasida vaqt o'tadi. O'zgaruvchan bozorda narx o'sha 20-100ms ichida uchib ketishi mumkin. Yechim: biroz tajovuzkor limit order yuborish (bufer bilan).
-
O'tkazib yuborilgan bajarilishlar. Agar narx sizning darajangizni bitta tickda "teshib o'tsa" (flash crash) va orqaga qaytsa — siz vaqtida javob bera olmasligingiz mumkin. Kitobda o'tirgan oddiy limit order bajarilgan bo'lardi; virtual order esa yo'q.
-
Holatni boshqarish. Virtual orderlar xotirada yashaydi. Jarayon qulasa — orderlar yo'qoladi. Yechim: qayta ishga tushirilganda tiklanadigan doimiy saqlash (Redis, SQLite, fayl).
6. Shartli/Aqlli Orderlar: Order Kombinatorikasi
Bitta order yetarli bo'lmaganda, treyderlar ularni shartli konstruksiyalarga birlashtiradi. Ba'zilari birjalarda tabiiy qo'llab-quvvatlanadi, boshqalari dasturiy tarzda amalga oshiriladi.
OCO (One Cancels Other)
Ikki order bog'langan: agar biri bajarilsa — ikkinchisi avtomatik ravishda bekor qilinadi. Klassik misol: siz long pozitsiyadasiz va ham take-profit, ham stop-loss o'rnatmoqchisiz. Qaysi biri birinchi bo'lib ishga tushsa — ikkinchisi bekor qilinishi kerak.
class OCOHandler:
"""
OCO: when one order fills, the other is cancelled.
"""
def __init__(self, exchange, symbol: str):
self.exchange = exchange
self.symbol = symbol
self.order_a_id: str | None = None
self.order_b_id: str | None = None
async def place(
self,
take_profit_price: float,
stop_loss_price: float,
qty: float,
):
tp = await self.exchange.create_limit_sell_order(
self.symbol, qty, take_profit_price
)
self.order_a_id = tp["id"]
sl = await self.exchange.create_order(
self.symbol, "stop", "sell", qty,
None, {"stopPrice": stop_loss_price}
)
self.order_b_id = sl["id"]
print(f"[OCO] TP @ {take_profit_price}, SL @ {stop_loss_price}")
async def monitor(self):
"""Checks statuses and cancels the paired order."""
while True:
if self.order_a_id:
a = await self.exchange.fetch_order(
self.order_a_id, self.symbol
)
if a["status"] == "closed":
print("[OCO] take-profit filled, cancelling stop-loss")
await self.exchange.cancel_order(
self.order_b_id, self.symbol
)
break
if self.order_b_id:
b = await self.exchange.fetch_order(
self.order_b_id, self.symbol
)
if b["status"] == "closed":
print("[OCO] stop-loss filled, cancelling take-profit")
await self.exchange.cancel_order(
self.order_a_id, self.symbol
)
break
await asyncio.sleep(0.5)
Bracket order
Uch komponentli konstruksiya: birlamchi kirish orderi + chiqish uchun OCO (take-profit + stop-loss). Aslida, bitta chaqiruvda to'liq savdo hayot sikli:
- Kirish: limit sotib olish orderi
- Take-profit: limit sotish orderi (yuqorida)
- Stop-loss: stop-market sotish orderi (pastda)
Kirish bajarilganda, TP va SL avtomatik ravishda joylashtiriladi. Ulardan biri bajarilganda — ikkinchisi bekor qilinadi.
If-Then Mantiq
Eng moslashuvchan variant — ixtiyoriy shartlar bilan order zanjirlari:
rules = [
{
"condition": {"symbol": "BTC/USDT", "price_above": 50000},
"action": {"type": "market_buy", "symbol": "ETH/USDT", "qty": 10},
"then": [
{
"condition": {"symbol": "ETH/USDT", "price_above": 4000},
"action": {"type": "market_sell", "symbol": "ETH/USDT", "qty": 10},
},
{
"condition": {"symbol": "ETH/USDT", "price_below": 3500},
"action": {"type": "market_sell", "symbol": "ETH/USDT", "qty": 10},
},
]
}
]
Bunday konstruksiyalar hech qanday birja tomonidan tabiiy ravishda qo'llab-quvvatlanmaydi — faqat dasturiy amalga oshirish orqali. Bu algotrading tizimlari muqarrar ravishda o'zining order boshqaruv qatlamini rivojlantirishining sabablaridan biridir.
7. Market Meykerlar Ixtisoslashtirilgan Order Turlaridan Qanday Foydalanadi
Market making — o'z olamiga ega bo'lgan soha, va orderlar to'plami ham unga mos keladi. Market meykerning vazifasi — spreddan foyda ko'rib, doimiy ravishda bid va ask kotirovkalarini berish, shu bilan birga adverse selection'ni (xabardor treyder siz bilan qarama-qarshi savdo qilgan holatni) minimallashtirish.
Post-only — Majburiy Talab
Market meyker uchun post-only tanlov emas — bu talab. Agar orderingiz tasodifan taker sifatida bajarilsa — maker rebatini olish o'rniga siz taker komissiyasini to'laysiz. Kuniga minglab orderlar bo'yicha bu falokatli.
async def quote(exchange, symbol, mid_price, half_spread, qty):
bid_price = mid_price - half_spread
ask_price = mid_price + half_spread
bid = await exchange.create_order(
symbol, "limit", "buy", qty, bid_price,
{"postOnly": True} # CRITICAL for market makers
)
ask = await exchange.create_order(
symbol, "limit", "sell", qty, ask_price,
{"postOnly": True}
)
return bid, ask
Hidden orderlar
Ba'zi birjalarda (Kraken, Bitfinex) yashirin orderlar mavjud — ular order kitobida ko'rinmaydi, lekin birjada bor va matchingda ishtirok etadi. Kelishuv: siz maker sifatida ham taker komissiyalarini to'laysiz, lekin anonimlikka ega bo'lasiz.
Market meyker uchun bu — inventarni boshqarish vositasi: agar katta pozitsiya to'planib qolgan bo'lsa, uni bozorga niyatingizni oshkor qilmasdan yopish uchun yashirin order joylashtirishingiz mumkin.
Pegged orderlar
Eng yaxshi bid/askka bog'langan order. Masalan, Coinbase Advanced Trade'da siz eng yaxshi bidni avtomatik kuzatib boradigan va har doim navbat boshida turadigan order joylashtira olasiz. Bu birja darajasidagi tabiiy chasing order — ammo bu hamma joyda mavjud emas.
Ommaviy order boshqaruvi
Professional market meykerlar bitta HTTP so'rovida bir vaqtning o'zida o'nlab orderlarni bekor qilish va joylashtirish uchun batch API'lardan foydalanadi. Binanceda bu batchOrders, Bybitda esa — place-batch-order. Bu kechikish va rate limit bosimini kamaytiradi.
8. Order Turlari Taqqoslash Jadvali
| Order Turi | Bajarilish Kafolati | Narx Kafolati | Kitobda Ko'rinadi | Birjalarda Tabiiy | Amalga Oshirish Murakkabligi |
|---|---|---|---|---|---|
| Market | Ha | Yo'q | Yo'q (darhol) | Ha | Yo'q |
| Limit | Yo'q | Ha | Ha | Ha | Yo'q |
| Stop-market | Ha (trigerdan keyin) | Yo'q | Yo'q | Ha | Yo'q |
| Stop-limit | Yo'q | Ha | Yo'q (trigergacha) | Ha | Yo'q |
| Trailing stop | Ha (trigerdan keyin) | Yo'q | Yo'q | Qisman | Past |
| Iceberg | Yo'q | Ha | Qisman | Qisman | O'rta |
| Post-only | Yo'q | Ha | Ha | Ha | Yo'q |
| TWAP | Yo'q (bo'laklarga bog'liq) | Yo'q | Qisman | Yo'q | O'rta |
| VWAP | Yo'q | Yo'q | Qisman | Yo'q | Yuqori |
| Chasing limit | Limitdan yuqori | Qisman | Ha (joriy order) | Yo'q | O'rta |
| Vaqtga asoslangan | Turga bog'liq | Turga bog'liq | Yo'q (T vaqtgacha) | Yo'q | Past |
| Virtual/Sintetik | Limitdan past | Turga bog'liq | Yo'q | Yo'q | O'rta |
| OCO | Ha (ikkitadan biri) | Qisman | Ha (ikkalasi) | Qisman | O'rta |
| Bracket | Ha | Qisman | Ha | Kam uchraydi | Yuqori |
| Hidden | Yo'q | Ha | Yo'q | Kam uchraydi | Yo'q |
| Pegged | Yo'q | Dinamik | Ha | Juda kam uchraydi | Yuqori (dasturiy bo'lsa) |
Xulosa: Strategiyaning Qurilish Bloki Sifatida Order
Order turlari shunchaki "interfeysdagi tugmalar" emas. Ular har qanday savdo tizimining bajarish qatlami qurilгan fundamental primitivlardir. "Strategiya backtestda foydali" va "strategiya ishlab chiqarishda foydali" o'rtasidagi farq ko'pincha aynan shu yerda — orderlarni birjaga qanday yuborishingizda yotadi.
Bir necha amaliy xulosalar:
- Standart orderlardan boshlang, nuanslarni tushunganingizga ishonch hosil qiling (stop-limit va stop-market, IOC va FOK). Ko'pchilik xatolar aynan shu yerda sodir bo'ladi.
- Virtual orderlar grid botlar uchun majburiy. Agar siz 50 dan ortiq order joylashtirsangiz — ularning barchasini birjaga yubormang.
- Chasing bajarilish darajasi narxdan muhimroq bo'lganda kerak. Lekin har doim max_chase_distance ni belgilang — aks holda juda uzoqqa siljib ketishingiz mumkin.
- Vaqtga asoslangan bajarish — nisha, ammo funding arbi va voqealarga asoslangan strategiyalar uchun kuchli vosita.
- Maxsus order boshqaruv qatlami har qanday jiddiy algotrading tizimi uchun muqarrar. Birjaning tabiiy order turlari yetarli emas.
Agar siz savdo tizimi qurayotgan bo'lsangiz va chuqurroq borishni istasangiz — order kitobidagi navbat pozitsiyasi, CCXT'dagi WebSocket usullari va funding stavkasi arbitraji haqidagi maqolalarimizga qarang.
Havolalar va Manbalar
- CCXT Library — kripto birjalar bilan ishlash uchun yagona kutubxona, 100+ birjani qo'llab-quvvatlaydi
- Binance API Documentation — Binance order turlari hujjatlari
- Bybit API v5 — Bybit hujjatlari, jumladan batch orderlar
- Moallemi, C. & Yuan, K. (2017). The Value of Queue Position in a Limit Order Book. Columbia Business School Research Paper
- Cartea, A., Jaimungal, S., & Penalva, J. (2015). Algorithmic and High-Frequency Trading. Cambridge University Press
- Avellaneda, M. & Stoikov, S. (2008) — High-frequency trading in a limit order book. Quantitative Finance
- Erik Rigtorp — Order Queue Position Estimation — navbat pozitsiyasini baholash bo'yicha materiallar
- Trading Technologies (TT) — ilg'or order turlariga ega professional platforma
Authors
Trading-systems engineer
Trading-systems engineer building bots since 2017: cross-exchange arbitrage (connected up to 30 venues), cointegration-based pairs arbitrage across spot and futures, scalping, news and sentiment-driven strategies, trend algorithms, and portfolio management and balancing algorithms. Also builds sub-millisecond order execution, big-data warehouses, backtesting engines, AI agents, and trading interfaces (incl. open-source profitmaker.cc). Stack: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, architecture.