Алгоритмдик Трейдингдеги Ордер Түрлөрү: Chasing менен Лимиттен Виртуалдык Ордерлерге чейин
Жаңы баштаган адам биржа терминалын ачканда, ал эки баскычты көрөт: "Сатып алуу" жана "Сатуу". Алго-трейдер өз кодун ачканда, ал жыйырма жети ордер түрүн, үч абстракция деңгээлин жана ноутбукту жаап, базарда бадыраң сатуу дегендин артынан жүргүзгүсү келтирген бир топ четки учурларды көрөт. Бирок, өкүнүчтүү болсо да, бадыраңдар силерге 3:59 UTC-де funding rate арбитражын жүргүзүүгө мүмкүнчүлүк беришпейт — андыктан түз эле маселеге өтөлү.
Бул макалада биз негизги биржа ордерлеринен баштап, жалгыз гана сиздин системаңызда жашаган жана эч качан ордер китебинде пайда болбогон синтетикалык виртуалдык түзүлүштөргө чейинки бүткүл жолду басып өтөбүз. TypeScript, Python, бир аз оору жана бир аз агартуу күтүлүүдө.
1. Стандарттуу Биржа Ордерлери: Өткөрүп Жиберип Болбой турган Негиз
Стандарттуу ордер түрлөрүнүн классификациясы: маркеттен айсбергге чейин
Татаал нерсе куруунун алдында, негизги куруу блокторун туура түшүнгөнүбүзгө көз жеткиребиз керек. Канча адам stop-limit менен stop-market-ти чаташтырып, кийин эмне үчүн өз стобу "иштебей калганына" таң калаары таң калыштуу (спойлер: ал иштеп кеткен, бирок лимиттик ордер slippage айынан аткарылган эмес).
Market ордер
Эң жөнөкөй жана ошол эле учурда эң коркунучтуу түрү. Сиз биржага: "азыр, кандай гана жеткиликтүү баада болбосун сатып ал/сат" дейсиз. Биржа ордер китебинен эң жакшы баадан баштап ликвиддүүлүктү алат. Эң жакшы деңгээлдеги көлөм жетишсиз болсо — ал андан ары жылат.
Качан колдонуу керек: позициядан шашылыш чыгуу, ылдамдык баадан маанилүүрөөк болгон сигналды аткаруу.
Тузактар: сейрек нарыкта 100 BTC үчүн market ордер бааны бир нече пайызга жылдырышы мүмкүн. Таасирди эске албай market ордерлерди моделдештирген бэктесттер — таза кыял.
Limit ордер
Сиз так бааны көрсөтөсүз. Ордер ордер китебине түшөт жана бирөө сиздин бааңызга макул болгонго чейин күтөт. Эгер лимиттик сатып алуу ордеринин баасы учурдагы нарыктан жогору болсо — ал дароо аткарылат (market ордер сыяктуу, бирок кепилденген максималдуу баа менен).
Негизги жагы: лимиттик ордер аткарылууну кепилдебейт. Баа сиздин деңгээлиңизге жетип, тескери бурулушу мүмкүн, сизди кезекте калтырып (кезектеги позиция жөнүндөгү макалабызда толугураак).
Stop-market жана Stop-limit
Так ушул жерден чаташуу башталат. Эки түрү тең иштөө баасына (stop price) жеткенде активдешкен "уктап жаткан" ордерлер. Бирок:
- Stop-market: иштеп кеткенде market ордерге айланат. Аткарылууну кепилдейт, бирок бааны эмес.
- Stop-limit: иштеп кеткенде лимиттик ордерге айланат. Бааны кепилдейт (көрсөтүлгөндөн жаманыраак эмес), бирок аткарылууну эмес.
Туруксуз крипто нарыгында stop-limit "өтүп кетиши" мүмкүн — баа стопту бузуп өттү, лимиттик ордер коюлду, бирок нарык мурунтан эле учуп өттү. Сизде аткарылбаган лимиттик ордер жана өсүп бара жаткан чыгым калат. Так ушул себептен stop-loss үчүн stop-market көбүрөөк колдонулат.
Trailing stop
Бааны белгиленген аралыкта "кубалаган" стоп. Баа көтөрүлөт — стоп да жогору жылат. Баа түшөт — стоп ордунда калат. Тренддик стратегияларда пайданы коргоо үчүн пайдалуу.
Биржа колдоосу: бардык биржалар да табигый trailing stop-ду колдобойт. Алго-трейдерлер аны көбүнчө программалык түрдө ишке ашырышат — бул параметрлерге (callback rate, активдештирүү баасы, кадам өлчөмү) көбүрөөк көзөмөл берет.
Iceberg ордер
Жалпы көлөмдүн бир бөлүгү гана ордер китебинде көрүнгөн ордер. Сиз 1000 BTC сатып алгыңыз келет, бирок китепте 10ун гана көрсөтөсүз. Биринчи 10у аткарылганда — кийинки 10у пайда болот.
Эмне үчүн: нарыктан чыныгы ниеттериңизди жашыруу үчүн. Китептеги чоң ордер баарына "бирөө чоң көлөмдө сатып алгысы/саткысы келет" деген сигнал берет. Жооп катары HFT алгоритмдери front-running жасай башташат, ал эми баа сизден алыстайт.
Эскертүү: көптөгөн крипто биржаларда айсберг ордерлер же колдоого алынбайт, же бирдей көлөмдөрдүн үлгүсү аркылуу оңой аныкталат. Өнүккөн алгоритмдер көрүнгөн бөлүктүн өлчөмүн кокустандырышат.
Time-in-force параметрлери: GTC, GTD, IOC, FOK
Булар өзүнчө ордер түрлөрү эмес, тескерисинче time-in-force параметрлери — ордер канча убакыт жашайт:
| Параметр | Толук аталышы | Жүрүм-туруму |
|---|---|---|
| GTC | Good Till Cancelled | Токтотулгуча жашайт. Стандарттуу default |
| GTD | Good Till Date | Көрсөтүлгөн күн/убакытка чейин жашайт |
| IOC | Immediate or Cancel | Дароо аткарылат (толук же жарым-жартылай), калганы жокко чыгарылат |
| FOK | Fill or Kill | Гана толук жана дароо аткарылат. Мүмкүн болбосо — толугу менен жокко чыгарылат |
IOC жана FOK айырмасы: айырма маанилүү. IOC жарым-жартылай аткарылышы мүмкүн — сиз 100 BTC сатып алгыңыз келди, 3үн сатып алдыңыз, калганы жокко чыгарылды. FOK болсо же толугу менен, же такыр эле жок.
Post-only (жалгыз Maker)
Ордер китебине maker катары кирүүсү кепилденген жана эч качан taker катары аткарылбаган ордер. Эгер коюу учурунда баа дароо аткарылууга алып келсе — биржа аны четке кагат (же биржага жараша бааны тууралайт).
Эмне үчүн: maker комиссиялары адатта taker комиссияларынан төмөн (Binance-де — VIP деңгээлдер үчүн 0,02% жана 0,04%). Күнүнө миңдеген ордер койгон маркет-мейкер үчүн комиссиянын айырмасы — пайда менен чыгымдын ортосундагы айырма.
2. TWAP жана VWAP: Институттар Ордер Китебинде Пилди Кантип Жашырышат
Хедж-фонд 50 миллион долларлык позиция сатып алгысы келгенде, ал бир гана market ордер коёт эмес. Ал аткаруу алгоритмдерин колдонот — чоң ордерди көптөгөн кичине бөлүктөргө бөлүп, аларды убакыт бою аткарган, нарыкка таасирди азайткан алгоритмдер.
TWAP (Time-Weighted Average Price)
Идея абдан жөнөкөй: жалпы көлөмдү тең бөлүктөргө бөлүп, тең убакыт аралыктарында аткаруу.
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 акылдуураак: ал típik соода көлөмүнүн профилин эске алат. Эгер күндүзгү көлөмдүн 30%ы адатта саат 9:00дан 10:00го чейин соодаланса, VWAP ордердин 30%ын так ошол терезеде аткарат. Максат — орточо аткаруу баасын нарыктык VWAP-ка мүмкүн болушунча жакындатуу.
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 менен VWAP-тын айырмасы: TWAP жөнөкөйрөөк жана божомолдонгонураак. VWAP жакшыраак орточо баа берет, бирок ишенимдүү көлөм профилин талап кылат. Көлөмдөр wash-trade жасалышы мүмкүн болгон крипто нарыгында VWAP профилин этияттык менен куруу керек.
3. Chasing менен Limit: Ордериңиз Бааны Кубалоону Билгенде
Chasing limit: ордер тууралоого боло турган агрессивдүүлүк менен кыймылдаган бааны кубалайт
Эми иштер чындап эле кызыктуу боло баштайт. Стандарттуу лимиттик ордер — пассивдүү нерсе: ал ордер китебинде отуруп күтөт. Баа кыймылдаса — ордер аткарылбай калат. Алго-трейдер үчүн бул көбүнчө кабыл алынгыс: кирүү сигналы иштеп кетти, бирок нарык 0,1%га жылгандыктан позиция курулган жок.
Chasing limit order — бул лимиттик ордердин айланасындагы программалык оролуш, ал:
- Учурдагы эң жакшы баада (же кичине offset менен) лимиттик ордер коёт
- Бааны WebSocket аркылуу байкайт
- Эгер баа ордерден алыстаса — аны токтотуп, учурдагы баага жакыныраак кайра коёт
- Ордер аткарылганча же уруксат берилген четтөөдөн ашканга чейин кайталайт
Негизги Параметрлер
- chase_interval_ms — ордерди канчалык көп текшерип, кайра коюу керек. 100мс — агрессивдүү, 1000мс — бошоңдоо.
- max_chase_distance — ордер токтотулганга чейинки баштапкы баадан максималдуу четтөө. Качып бара жаткан нарыкты кубалоодон коргоо.
- aggression_level — лимиттик ордерди нарыктык баага канчалык жакын коюу керек.
0— эң жакшы bid/ask-та (пассивдүү),1— спрeдди кесип өтүү (агрессивдүү, иш жүзүндө taker). - chase_on_partial — ордер жарым-жартылай аткарылса, кубалоону улантуу керекпи.
TypeScript Ишке Ашыруусу
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 Зыян Келтире турган Учурлар
Chasing — күчтүү курал, бирок аны чыгым генераторуна айландыруу оңой:
- Cancel/replace спамы. Ар бир жокко чыгаруу жана кайра коюу API үчүн жүктөм болуп саналат. Биржалар сурамдарды чектейт (rate limit), ал эми агрессивдүү chasing API ачкычыңыздын бөгөттөлүшүнө алып келиши мүмкүн.
- Терс тандоо (adverse selection). Эгер баа сизден качып жатса — нарык сиз билбеген нерсени билиши мүмкүн. Мындай кырдаалда бааны кубалоо чокуда сатып алууну билдирет.
- Maker-ден Taker-ге өтүү. Жогорку агрессивдүүлүк менен сиз иш жүзүндө taker комиссияларын төлөйсүз, бирок кечигүү менен (жокко чыгаруу + жаңы ордер). Кээде жөн эле market ордер коюу оңоюраак.
4. Убакытка Негизделген Ордерлер: Миллисекунддук Тактык
Ордерди "X баада" эмес, "T убактысында" аткаруу зарыл болгон учурлар бар. Кызык угулаby? Чынында бул толук стратегиялар классы.
Колдонуу учурлары
Funding rate арбитражы. Түбөлүк фьючерстерде funding ар 8 саат сайын төлөнөт (Binance-де 00:00, 08:00, 16:00 UTC). Эгер funding ставкасы = +0,1% болсо, эсептешүү учурунда short позицияда болуу керек. Стратегия: эсептешүүдөн бир нече секунд мурун short ачуу, funding жыйноо, позицияны жабуу. Убакыттын тактыгы чечүүчү — бир секунд кечигүү өткөрүп жиберилген funding дегенди билдирет.
Сессиялардын ачылышы/жабылышы. Салттуу нарыктарда жана айрым крипто туундуларда туруктуу сессиялар бар. Ачылуу аукциону (NYSE, CME) — ликвиддүүлүктүн чокусуна жеткен учур. Аукциондон 100мс мурун ордер коюу — артыкчылык.
Жаңылыктарга негизделген аткаруу. Инфляция маалыматтары пландаштырылган убакытта жарыяланат. Алгоритм санды жаңылыктар лентасынан талдап, 50мс ичинде ордер коёт. Бул жерде убакытка негизделген аткаруу окуяга негизделген логика менен айкалышат.
Ишке ашыруу
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);
Маанилүү эскертүү: убакытка негизделген ордердин тактыгы сиздин кодуңуз менен эмес, биржага чейинки тармак кечигүүсү (latency) менен чектелет. Эгер API-ге пинг убагыңыз 50мс болсо, кемчиликсиз busy-wait деле 50мс дельта берет. Олуттуу HFT үчүн co-location колдонулат — сервер физикалык жактан биржанын matching engine-инин жанында жайгашат.
5. Виртуалдык/Синтетикалык Ордерлер: Системаңыздагы Көрүнбөстөр
Виртуалдык ордерлер: триггер иштегенге чейин алар жалгыз гана боттун эсинде жашайт
Бул, балким, алго-трейдердин куралынын арасындагы эң баалуулугу азыраак баалаган каражат. Виртуалдык ордер (синтетикалык ордер деп да аталат) — жалгыз гана сиздин системаңызда жашаган ордер. Ал триггер шарты аткарылганга чейин (адатта — баа белгилүү бир деңгээлге жеткенге чейин) биржага жиберилбейт.
Бул Кантип Иштейт
- Сиздин алгоритмиңиз чечим кабыл алат: "BTC-ды 40 000 долларга сатып алгым келет"
- Биржага лимиттик ордер жиберүүнүн ордуна, ал эсте виртуалдык ордер түзөт
- WebSocket баа агымына жазылат
- Bid/ask 40 000 долларга жеткенде — биржага чыныгы market же лимиттик ордер жиберилет
Виртуалдык Ордерлер Эмне Үчүн Маанилүү
Маалымат сызылып чыкпайт. Сиздин ордериңиз ордер китебинде көрүнбөйт. Эч ким — башка трейдерлер да, HFT алгоритмдери да, атүгүл биржанын өзү да — аткарылуу учуруна чейин сиздин ниеттериңиз жөнүндө билбейт. Бул күчтөрдүн тең салмактуулугун түп-тамырынан өзгөртөт.
Front-running-дан коргоо. Крипто биржаларда, өзгөчө азыраак ачык болгондорунда, чоң лимиттик ордерлер жөнүндөгү маалыматтын front-running үчүн колдонулушу мүмкүн деген негиздүү шектөө бар (бул жөнүндө изилдөөлөр да бар). Виртуалдык ордерлер бул тобокелди жоюшат.
Grid боттор. Классикалык grid бот ар кандай баа деңгээлдеринде 50-200 ордерден турган торду жайгаштырат. Эгер сиз аларды баарын биржага жиберсеңиз — бул китепте: (а) баарына көрүнгөн, (б) биржадагы ордер лимитин колдонгон (адатта аккаунт үчүн 200-300 ачык ордер), (в) баа катуу кыймылдаса, алардын баары аткарылып, сизде эбегейсиз позиция калат дегенди билдирген 200 ордер. Виртуалдык ордерлер бул үч көйгөйдү тең чечет.
Кулап жаткан бычактарды кармоо. Стратегия: учурдагы баадан -5%, -10%, -15% төмөн виртуалдык сатып алуу ордерлерин коюу. Нарык кулап баштаса — ордерлер бирден-бирден иштеп кетет. Кулабаса — сиз эч нерсеге тобокелдик кылбайсыз жана биржанын ордер слотторун колдонбойсуз.
TypeScript Ишке Ашыруусу
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
);
}
}
Виртуалдык Ордерлердин Начар Жактары
-
Кечигүү боштугу. Сиз бааны көргөн учур менен чыныгы ордер биржага жеткен учур ортосунда убакыт өтөт. Туруксуз нарыкта баа так ошол 20-100мс ичинде учуп кетиши мүмкүн. Чечим: бир аз агрессивдүү лимиттик ордер жиберүү (буфер менен).
-
Өткөрүп жиберилген аткаруулар. Эгер баа сиздин деңгээлиңизди бир тикте (flash crash) "тешип өтүп" кайра кайтып келсе — сиз убагында аракет кыла албашыңыз мүмкүн. Китепте отурган кадимки лимиттик ордер аткарылмак; виртуалдык — жок.
-
Абалды башкаруу. Виртуалдык ордерлер эсте жашайт. Процесс кулап калса — ордерлер жоголот. Чечим: кайра иштеткенде калыбына келтирүү менен туруктуу сактоо (Redis, SQLite, файл).
6. Шарттуу/Акылдуу Ордерлер: Ордер Комбинаторикасы
Бир ордер жетишсиз болгондо, трейдерлер аларды шарттуу түзүлүштөргө бириктиришет. Айрымдары биржаларда табигый түрдө колдоого алынат, башкалары программалык түрдө ишке ашырылат.
OCO (One Cancels Other)
Эки ордер байланышкан: эгер бирөө аткарылса — экинчиси автоматтык түрдө жокко чыгарылат. Классикалык мисал: сиз long позицияда турасыз жана take-profit менен stop-loss экөөнү тең орнотууну каалайсыз. Кайсынысы биринчи иштеп кетсе — экинчиси жокко чыгарылышы керек.
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
Үч компоненттен турган түзүлүш: кирүү үчүн негизги ордер + чыгуу үчүн OCO (take-profit + stop-loss). Мааниси боюнча, бир гана чакырууда мамиленин толук өмүрлүк цикли:
- Кирүү: сатып алууга лимиттик ордер
- Take-profit: сатууга лимиттик ордер (жогоруда)
- Stop-loss: сатууга stop-market ордер (төмөндө)
Кирүү аткарылганда, TP менен SL автоматтык түрдө коюлат. Алардын бирөө аткарылганда — экинчиси жокко чыгарылат.
If-Then Логикасы
Эң ийкемдүү вариант — каалаган шарттар менен ордер чынжырлары:
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},
},
]
}
]
Мындай түзүлүштөр эч бир биржада табигый түрдө колдоого алынбайт — жалгыз гана программалык ишке ашыруу аркылуу. Бул алготрейдинг системаларынын сөзсүз түрдө өз ордерлерди башкаруу катмарын өнүктүрүшүнүн себептеринин бири.
7. Маркет-Мейкерлер Адистештирилген Ордер Түрлөрүн Кантип Колдонушат
Market making — өзүнчө ааламы бар тармак, жана ордер каражаттарынын жыйындысы да ошого туура келет. Маркет-мейкердин ишинин мазмуну — спредден пайда алуу менен bid жана ask-ты үзгүлтүксүз белгилөө, ошону менен катар adverse selection-ду (маалыматтуу трейдер сизге каршы соода жасаган абалды) азайтуу.
Post-only — Милдеттүү Талап
Маркет-мейкер үчүн post-only — тандоо эмес, талап. Эгер сиздин ордериңиз кокустан taker катары аткарылса — maker rebate алуунун ордуна сиз taker комиссиясын төлөйсүз. Күнүнө миңдеген ордер боюнча бул кырсык.
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 ордерлер
Айрым биржаларда (Kraken, Bitfinex) жашыруун ордерлер жеткиликтүү — алар ордер китебинде көрүнбөйт, бирок биржада бар жана matching-ге катышат. Мамиле: сиз maker катары да taker комиссияларын төлөйсүз, бирок анонимдүүлүккө ээ болосуз.
Маркет-мейкер үчүн бул — товардык запасты (inventory) башкаруу каражаты: эгер чоң позиция топтолуп калса, аны нарыкка ниетиңизди ачыкка чыгарбай тарамдоо үчүн жашыруун ордер коюуга болот.
Pegged ордерлер
Эң жакшы bid/ask-ка байланган ордер. Мисалы, Coinbase Advanced Trade-те сиз эң жакшы bid-ды автоматтык түрдө байкап туруучу жана дайыма кезектин башында турган ордер коё аласыз. Бул — биржа деңгээлиндеги табигый chasing ордер, бирок бул баары жеринде бирдей жеткиликтүү эмес.
Жалпы ордер башкаруу
Кесипкөй маркет-мейкерлер бир HTTP сурамында бир нече ондогон ордерлерди бир мезгилде жокко чыгаруу жана коюу үчүн batch API-лерди колдонушат. Binance-де бул batchOrders, Bybit-те — place-batch-order. Бул кечигүү жана rate limit басымын азайтат.
8. Ордер Түрлөрүнүн Салыштыруу Кестеси
| Ордер Түрү | Аткаруу Кепилдиги | Баа Кепилдиги | Китепте Көрүнөт | Биржаларда Табигый | Ишке Ашыруу Татаалдыгы |
|---|---|---|---|---|---|
| Market | Ооба | Жок | Жок (дароо) | Ооба | Жок |
| Limit | Жок | Ооба | Ооба | Ооба | Жок |
| Stop-market | Ооба (иштеп кеткенден кийин) | Жок | Жок | Ооба | Жок |
| Stop-limit | Жок | Ооба | Жок (иштеп кеткенге чейин) | Ооба | Жок |
| Trailing stop | Ооба (иштеп кеткенден кийин) | Жок | Жок | Жарым-жартылай | Төмөн |
| Iceberg | Жок | Ооба | Жарым-жартылай | Жарым-жартылай | Орточо |
| Post-only | Жок | Ооба | Ооба | Ооба | Жок |
| TWAP | Жок (бөлүктөргө көз каранды) | Жок | Жарым-жартылай | Жок | Орточо |
| VWAP | Жок | Жок | Жарым-жартылай | Жок | Жогору |
| Chasing limit | Limit-ден жогору | Жарым-жартылай | Ооба (учурдагы ордер) | Жок | Орточо |
| Убакытка негизделген | Түргө көз каранды | Түргө көз каранды | Жок (T убакытка чейин) | Жок | Төмөн |
| Виртуалдык/Синтетикалык | Limit-ден төмөн | Түргө көз каранды | Жок | Жок | Орточо |
| OCO | Ооба (экөөнүн бирөө) | Жарым-жартылай | Ооба (экөө тең) | Жарым-жартылай | Орточо |
| Bracket | Ооба | Жарым-жартылай | Ооба | Сейрек | Жогору |
| Hidden | Жок | Ооба | Жок | Сейрек | Жок |
| Pegged | Жок | Динамикалык | Ооба | Абдан сейрек | Жогору (программалык болсо) |
Жыйынтык: Стратегиянын Куруу Блогу Катары Ордер
Ордер түрлөрү жөн гана "интерфейстеги баскычтар" эмес. Алар кандай гана соода системасынын аткаруу катмары курулган негизги примитивдер. "Стратегия бэктестте пайдалуу" менен "стратегия өндүрүштө пайдалуу" ортосундагы айырма көбүнчө так ушул жерде — ордерлерди биржага так кантип жиберериңизде жатат.
Бир нече практикалык жыйынтык:
- Стандарттуу ордерлерден баштаңыз, нюанстарды түшүнгөнүңүзгө көз жеткириңиз (stop-limit жана stop-market, IOC жана FOK). Көпчүлүк каталар так ушул жерде болот.
- Виртуалдык ордерлер grid боттор үчүн милдеттүү. Эгер сиз 50дөн ашык ордер коюп жатсаңыз — аларды баарын биржага жибербеңиз.
- Chasing аткаруу деңгээли баадан маанилүүрөөк болгондо керек. Бирок дайыма max_chase_distance коюңуз — болбосо өтө алыска жылып кетишиңиз мүмкүн.
- Убакытка негизделген аткаруу — тар адистештирилген, бирок funding арбитражы жана окуяга негизделген стратегиялар үчүн күчтүү.
- Жеке ордерлерди башкаруу катмары ар кандай олуттуу алготрейдинг системасы үчүн сөзсүз керек. Биржанын табигый ордер түрлөрү жетишсиз.
Эгер сиз соода системасын куруп жатсаңыз жана тереңирээк баргыңыз келсе — ордер китебиндеги кезектеги позиция, CCXT-теги WebSocket методдору жана funding rate арбитражы жөнүндөгү макалаларыбызды караңыз.
Шилтемелер жана Булактар
- CCXT Library — крипто биржалар менен иштөө үчүн бириктирилген китепкана, 100+ биржаны колдойт
- Binance API Documentation — Binance ордер түрлөрүнүн документтери
- Bybit API v5 — Bybit документтери, анын ичинде batch ордерлер
- 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 — кезектеги позицияны баалоо боюнча материалдар
- Trading Technologies (TT) — өнүккөн ордер түрлөрү бар кесипкөй платформа
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.