OCO GELİŞMİŞ

OCO Emirleri

One-Cancels-the-Other — 1 Stop-Loss ve kademeli Take-Profit emirleri ile pozisyonunuzu yönetin. SL tetiklendiğinde tüm TP emirleri otomatik iptal edilir; her TP tetiklendiğinde diğerleri izlemeye devam eder.

https://devapi.tradewise.com.tr/api/v1/oco-orders
Genel Bakış Grup Modeli Fiyat Kademeleri POST Oluştur POST Emre Bağla GET Listele DELETE İptal Durum Kodları Kod Örnekleri

Genel Bakış

OCO (One-Cancels-the-Other) emri, bir pozisyon için aynı anda hem kademeli Take Profit hem de tek bir Stop Loss seviyesi tanımlamanızı sağlar.

Sentetik Emir: OCO emirleri borsaya gönderilmez; TradeWise altyapısında saklanır. Anlık fiyat akışı izlenir ve tanımlanan seviyeye ulaşıldığında aracı kuruma market satış emri iletilir.
📋
1. Grup Oluştur
1 SL + istediğin kadar kademeli TP emri tanımla
👁
2. Fiyat İzlenir
TradeWise anlık tick akışını gerçek zamanlı takip eder
3. Otomatik Tetikleme
TP kademesi veya SL seviyesine ulaşılınca market satış gönderilir

Grup Modeli

Her OCO grubu bir Stop Loss (SL) ve bir veya daha fazla Take Profit (TP) emrinden oluşur. SL emrinin id değeri tüm gruptaki emirlerin groupId'si olur.

Örnek: EREGL, 100 lot
idgroupIdorderTypepricequantity
1011012 (StopLoss)21,00100
1021011 (TakeProfit)22,2040
1031011 (TakeProfit)23,0040
1041011 (TakeProfit)24,0020
TP tetiklenince
Yalnızca o TP kademesi için market satış gider. Diğer TP'ler ve SL izlemeye devam eder.
SL tetiklenince
1. SL miktarı kadar market satış gider.
2. Gruptaki tüm aktif TP emirleri otomatik Cancelled yapılır.
3. Grup izlemeden çıkarılır.

BIST Fiyat Kademeleri

Tüm price değerleri BIST kademe kurallarına uygun olmalıdır. Geçersiz kademede fiyat gönderildiğinde API 400 Bad Request döner.

Fiyat Aralığı (TL) Kademe Geçerli Örnek Geçersiz Örnek
0,01 – 19,99 0,0115,43 ✓ 15,435 ✗
20,00 – 49,99 0,0222,20 ✓ 22,21 ✗
50,00 – 99,99 0,0565,05 ✓ 65,04 ✗
100,00 – 249,99 0,10145,60 ✓ 145,65 ✗
250,00 – 499,99 0,25330,00 ✓ 330,10 ✗
500,00 – 999,99 0,50725,00 ✓ 725,25 ✗
1.000 – 2.499,991,001.250,00 ✓1.250,50 ✗
2.500 ve üzeri 2,503.500,00 ✓3.501,00 ✗

OCO Emir Grubu Oluştur

1 Stop-Loss ve istediğiniz kadar kademeli Take-Profit emrini tek çağrıyla oluşturur.

POST /api/v1/oco-orders
Request Body
AlanTipZorunluAçıklama
brokerageCode string zorunlu Aracı kurum kodu (örn. "TradeWiseYatirim")
accountNumber string zorunlu Aracı kurum hesap numarası
symbol string zorunlu Hisse sembolü — örn. "EREGL"
stopLossPrice decimal zorunlu Zarar kes fiyatı. Tüm TP fiyatlarından düşük, BIST kademe uyumlu olmalıdır.
stopLossQuantity integer zorunlu Stop-Loss emrinin lot adedi.
takeProfitItems array zorunlu En az 1 eleman içermelidir. Her eleman { price, quantity } içerir.
takeProfitItems[].price decimal zorunlu Bu kademenin kâr al fiyatı. SL fiyatından yüksek, BIST kademe uyumlu olmalıdır.
takeProfitItems[].quantity integer zorunlu Bu kademenin lot adedi.
dueDate datetime? opsiyonel Son geçerlilik tarihi (ISO 8601). Bu tarihten sonra emir izlenmez.
notes string? opsiyonel Serbest metin not (max 500 karakter)
Örnek İstek
curl -X POST https://devapi.tradewise.com.tr/api/v1/oco-orders \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "brokerageCode": "TradeWiseYatirim",
    "accountNumber": "123456",
    "symbol": "EREGL",
    "stopLossPrice": 21.00,
    "stopLossQuantity": 100,
    "takeProfitItems": [
      { "price": 22.20, "quantity": 40 },
      { "price": 23.00, "quantity": 40 },
      { "price": 24.00, "quantity": 20 }
    ],
    "dueDate": "2026-06-30T23:59:59Z",
    "notes": "Kademeli kâr al + zarar kes"
  }'
Yanıtlar
200 OK Grup başarıyla oluşturuldu — SL emri döner
{
  "success": true,
  "message": "OCO emir grubu başarıyla oluşturuldu.",
  "data": {
    "id": 101,
    "groupId": 101,
    "userId": 42,
    "accountNumber": "123456",
    "symbol": "EREGL",
    "orderType": 2,
    "quantity": 100,
    "price": 21.00,
    "status": 1,
    "triggeredPrice": null,
    "triggeredDate": null,
    "dueDate": "2026-06-30T23:59:59Z",
    "notes": "Kademeli kâr al + zarar kes",
    "triggerErrorMessage": null,
    "createdDate": "2026-04-09T08:00:00Z",
    "updatedDate": null
  }
}
400 Bad Request Kademe hatası, miktar hatası veya zaten aktif grup var
{
  "success": false,
  "message": "EREGL için zaten aktif bir OCO grubunuz var. Önce mevcut emri iptal edin."
}

Broker Emrine Bağlı OCO (Pending OCO)

Önce broker'a normal alış emri verirsiniz, sonra dönen brokerOrderNo ile bu endpoint'i çağırırsınız. Broker emri Completed olunca gerçekleşme fiyatı üzerinden SL/TP fiyatları otomatik hesaplanır, BIST kademesine yuvarlanır ve klasik OCO grubu oluşturulur. Broker emri iptal edilirse bağlantı da düşer; siz hiçbir şey yapmazsınız.

Klasik OCO'dan farkı: Klasik POST /api/v1/oco-orders emirleri anında oluşturur ve tüm SL/TP fiyatlarını sabit ister. Pending OCO ise broker emri gerçekleşene kadar bekler ve seviyeleri yüzde olarak da kabul eder — gerçekleşme fiyatınızı önceden bilmediğiniz senaryolar için idealdir.
POST /api/v1/oco-orders/register-pending
Request Body
AlanTipZorunluAçıklama
brokerageCode string zorunlu Aracı kurum kodu (örn. "TradeWiseYatirim")
accountNumber string zorunlu Aracı kurum hesap numarası
brokerOrderNo string zorunlu Broker'a verdiğiniz alış emrinin numarası. Bu emir gerçekleşince OCO satırları oluşur.
symbol string zorunlu Hisse sembolü — örn. "EREGL". Broker emrindeki sembol ile eşleşmelidir.
stopLossQuantity integer zorunlu Stop-Loss emrinin lot adedi.
stopLossPercent decimal? yarı-opsiyonel Long için SL yüzdesi — örn. 3 = gerçekleşme fiyatından %3 aşağı. stopLossPrice ile birlikte verilemez; ikisinden biri girilmelidir.
stopLossPrice decimal? yarı-opsiyonel Sabit Stop-Loss fiyatı — BIST kademe uyumlu olmalıdır. stopLossPercent ile birlikte verilemez.
takeProfitItems array zorunlu En az 1 eleman. Her eleman { quantity, percent?, price? }.
takeProfitItems[].quantity integer zorunlu Bu kademenin lot adedi (en az 1).
takeProfitItems[].percent decimal? yarı-opsiyonel Long için TP yüzdesi — örn. 4.5 = gerçekleşme fiyatından %4.5 yukarı. price ile birlikte verilemez; ikisinden biri girilmelidir.
takeProfitItems[].price decimal? yarı-opsiyonel Sabit kâr al fiyatı — BIST kademe uyumlu olmalıdır. percent ile birlikte verilemez.
dueDate datetime? opsiyonel Aktive olan OCO grubu için son geçerlilik tarihi (ISO 8601).
notes string? opsiyonel Serbest metin not (max 500 karakter)
Yaşam Döngüsü
📩
1. Pending Kayıt
Bağlantı kaydedilir. Henüz OCO satırı yoktur.
2. Emir Gerçekleşince
Gerçekleşme fiyatı ile %'ler hesaplanır, BIST'e yuvarlanır, OCO satırları oluşur.
🚫
2b. Emir İptal Olursa
Bağlantı kaydı da silinir. OCO satırı oluşmaz.
Örnek İstek — yüzdelik SL + karışık TP
curl -X POST https://devapi.tradewise.com.tr/api/v1/oco-orders/register-pending \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "brokerageCode": "TradeWiseYatirim",
    "accountNumber": "123456",
    "brokerOrderNo": "ORDER-9876",
    "symbol": "EREGL",
    "stopLossQuantity": 100,
    "stopLossPercent": 3,
    "takeProfitItems": [
      { "quantity": 40, "percent": 4.5 },
      { "quantity": 40, "price": 23.00 },
      { "quantity": 20, "percent": 8 }
    ],
    "dueDate": "2026-06-30T23:59:59Z",
    "notes": "Gerçekleşmesini bekliyorum"
  }'
Örnek İstek — tam fiyatlı (yüzde kullanmadan)
curl -X POST https://devapi.tradewise.com.tr/api/v1/oco-orders/register-pending \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "brokerageCode": "TradeWiseYatirim",
    "accountNumber": "123456",
    "brokerOrderNo": "ORDER-9876",
    "symbol": "EREGL",
    "stopLossQuantity": 100,
    "stopLossPrice": 21.00,
    "takeProfitItems": [
      { "quantity": 40, "price": 22.20 },
      { "quantity": 40, "price": 23.00 },
      { "quantity": 20, "price": 24.00 }
    ]
  }'
Yanıtlar
200 OK data alanı bağlantı kaydının setupId değeridir (integer).
{
  "success": true,
  "message": "Bekleyen OCO bağlantısı kaydedildi. Emir gerçekleşince otomatik OCO oluşturulur.",
  "data": 4217
}
400 Bad Request Validasyon hatası veya bu broker emir numarası için zaten bekleyen kayıt var
{
  "success": false,
  "message": "Stop-Loss için yüzde ve fiyat birlikte verilemez; sadece birini girin.",
  "data": 0
}
Validasyon kuralları:
• SL için stopLossPercent veya stopLossPrice'tan tam olarak biri girilmelidir.
• Her TP için percent veya price'tan tam olarak biri girilmelidir.
• Fiyat girilirse BIST kademe aralığına uygun olmalı; yüzde girilen alanlar gerçekleşme sonrası otomatik yuvarlanır.
• Aynı brokerOrderNo için ikinci bir pending kayıt açılamaz.
• Şu an yalnızca long pozisyon (alış emri) destekleniyor — yüzdeler "yukarı" yönde uygulanır.

OCO Emir Satırlarını Listele

Belirtilen hesaba ait tüm OCO emir satırlarını döner. Her satır ya bir TP ya da bir SL emridir; groupId ile birbirine bağlıdır.

GET /api/v1/oco-orders
Query Parameters
ParametreTipZorunluAçıklama
brokerageCode string zorunlu Aracı kurum kodu
accountNumber string zorunlu Hesap numarası
Örnek İstek
curl -X GET "https://devapi.tradewise.com.tr/api/v1/oco-orders?brokerageCode=TradeWiseYatirim&accountNumber=123456" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"
Yanıt Alanları
AlanTipAçıklama
idintEmir satırının benzersiz kimliği
groupIdintGrubun kimliği — SL emrinin id değeridir
accountNumberstringHesap numarası
symbolstringHisse sembolü
orderTypeint1=TakeProfit, 2=StopLoss
quantityintBu satır için lot adedi
pricedecimalTetiklenme fiyatı
statusint1=Aktif, 2=Tetiklendi, 3=TetiklemeBaşarısız, 4=İptalEdildi
triggeredPricedecimal?Tetiklenme anındaki anlık fiyat
triggeredDatedatetime?Tetiklenme zamanı (UTC)
dueDatedatetime?Son geçerlilik tarihi
notesstring?Kullanıcı notu
triggerErrorMessagestring?Tetikleme hata mesajı (status=3 ise dolu)
Örnek Yanıt 200 OK
{
  "success": true,
  "message": "İşlem Başarılı",
  "data": [
    { "id": 101, "groupId": 101, "accountNumber": "123456", "symbol": "EREGL",
      "orderType": 2, "quantity": 100, "price": 21.00, "status": 1,
      "triggeredPrice": null, "triggeredDate": null, "createdDate": "2026-04-09T08:00:00Z" },
    { "id": 102, "groupId": 101, "accountNumber": "123456", "symbol": "EREGL",
      "orderType": 1, "quantity": 40, "price": 22.20, "status": 1,
      "triggeredPrice": null, "triggeredDate": null, "createdDate": "2026-04-09T08:00:00Z" },
    { "id": 103, "groupId": 101, "accountNumber": "123456", "symbol": "EREGL",
      "orderType": 1, "quantity": 40, "price": 23.00, "status": 1,
      "triggeredPrice": null, "triggeredDate": null, "createdDate": "2026-04-09T08:00:00Z" },
    { "id": 104, "groupId": 101, "accountNumber": "123456", "symbol": "EREGL",
      "orderType": 1, "quantity": 20, "price": 24.00, "status": 2,
      "triggeredPrice": 24.05, "triggeredDate": "2026-04-10T09:14:32Z", "createdDate": "2026-04-09T08:00:00Z" }
  ]
}

OCO Emir Grubunu İptal Et

Belirtilen emrin ait olduğu tüm gruptaki aktif emirleri iptal eder. Sadece status: 1 (Aktif) emirler iptal edilebilir.

DELETE /api/v1/oco-orders/{id}
Parametreler
ParametreYerTipAçıklama
id path integer Herhangi bir emir satırının ID'si (SL veya TP olabilir). Tüm grup iptal edilir.
brokerageCode query string Aracı kurum kodu
Örnek İstek
curl -X DELETE "https://devapi.tradewise.com.tr/api/v1/oco-orders/101?brokerageCode=TradeWiseYatirim" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"
200 OK
{
  "success": true,
  "message": "OCO emir grubu iptal edildi.",
  "data": true
}

Emir Durum Kodları

Her OCO emir satırının status (integer) ve orderType (integer) alanı bulunur.

status
KodDurumAçıklama
1 Aktif İzleniyor.
2 Tetiklendi Seviyeye ulaşıldı; market satış iletildi. TP mi SL mi tetiklendi bilgisi orderType'tan okunur.
3 Tetikleme Başarısız Seviye tetiklendi ancak emir gönderilemedi. triggerErrorMessage alanını inceleyin.
4 İptal Edildi Manuel iptal veya SL tetiklenince grup iptali.
orderType
KodTürTetiklenme Koşulu
1 TakeProfit Anlık fiyat ≥ price
2 StopLoss Anlık fiyat ≤ price

Kod Örnekleri

Popüler dillerde tam OCO emir akışı — grup oluştur, listele, iptal et.

JavaScript / Node.js
const JWT_TOKEN = 'YOUR_JWT_TOKEN';
const BASE_URL = 'https://devapi.tradewise.com.tr';
const headers  = { Authorization: `Bearer ${JWT_TOKEN}`, 'Content-Type': 'application/json' };

// OCO grup oluştur
async function createOcoGroup({ brokerageCode, accountNumber, symbol,
    stopLossPrice, stopLossQuantity, takeProfitItems, dueDate, notes }) {
  const res = await fetch(`${BASE_URL}/api/v1/oco-orders`, {
    method: 'POST',
    headers,
    body: JSON.stringify({ brokerageCode, accountNumber, symbol,
        stopLossPrice, stopLossQuantity, takeProfitItems, dueDate, notes })
  });
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return res.json();
}

// Listele
async function listOcoOrders(brokerageCode, accountNumber) {
  const params = new URLSearchParams({ brokerageCode, accountNumber });
  const res = await fetch(`${BASE_URL}/api/v1/oco-orders?${params}`, { headers });
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return res.json();
}

// İptal et
async function cancelOcoGroup(id, brokerageCode) {
  const res = await fetch(`${BASE_URL}/api/v1/oco-orders/${id}?brokerageCode=${brokerageCode}`, {
    method: 'DELETE', headers
  });
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return res.json();
}

// Kullanım
const group = await createOcoGroup({
  brokerageCode: 'TradeWiseYatirim',
  accountNumber: '123456',
  symbol: 'EREGL',
  stopLossPrice: 21.00,
  stopLossQuantity: 100,
  takeProfitItems: [
    { price: 22.20, quantity: 40 },
    { price: 23.00, quantity: 40 },
    { price: 24.00, quantity: 20 }
  ]
});
console.log(`Grup oluşturuldu: GroupId=${group.data.id}`);
Python
import requests

JWT_TOKEN = 'YOUR_JWT_TOKEN'
BASE_URL = 'https://devapi.tradewise.com.tr'
HEADERS  = {'Authorization': f'Bearer {JWT_TOKEN}', 'Content-Type': 'application/json'}

def create_oco_group(brokerage_id, account_number, symbol,
                     stop_loss_price, stop_loss_qty, take_profit_items,
                     due_date=None, notes=None):
    payload = {
        'brokerageCode': brokerage_id,
        'accountNumber':     account_number,
        'symbol':            symbol,
        'stopLossPrice':     stop_loss_price,
        'stopLossQuantity':  stop_loss_qty,
        'takeProfitItems':   take_profit_items,
    }
    if due_date: payload['dueDate'] = due_date
    if notes:    payload['notes']   = notes
    r = requests.post(f'{BASE_URL}/api/v1/oco-orders', json=payload, headers=HEADERS)
    r.raise_for_status()
    return r.json()

def list_oco_orders(brokerage_id, account_number):
    r = requests.get(f'{BASE_URL}/api/v1/oco-orders',
                     params={'brokerageCode': brokerage_id, 'accountNumber': account_number},
                     headers=HEADERS)
    r.raise_for_status()
    return r.json()

def cancel_oco_group(order_id, brokerage_id):
    r = requests.delete(f'{BASE_URL}/api/v1/oco-orders/{order_id}',
                        params={'brokerageCode': brokerage_id},
                        headers=HEADERS)
    r.raise_for_status()
    return r.json()

# Kullanım
result = create_oco_group(
    'TradeWiseYatirim', '123456', 'EREGL',
    stop_loss_price=21.00, stop_loss_qty=100,
    take_profit_items=[
        {'price': 22.20, 'quantity': 40},
        {'price': 23.00, 'quantity': 40},
        {'price': 24.00, 'quantity': 20},
    ]
)
print(f"Grup oluşturuldu: GroupId={result['data']['id']}")
C# / .NET
using System.Net.Http.Json;

public record TakeProfitItem(decimal Price, int Quantity);

public record CreateOcoGroupRequest(
    string BrokerageCode,
    string AccountNumber,
    string Symbol,
    decimal StopLossPrice,
    int     StopLossQuantity,
    List<TakeProfitItem> TakeProfitItems,
    DateTime? DueDate = null,
    string?   Notes   = null);

public class OcoOrderClient(string accessToken, string baseUrl = "https://devapi.tradewise.com.tr")
{
    private readonly HttpClient _http = new();

    private HttpRequestMessage NewRequest(HttpMethod method, string path)
    {
        var req = new HttpRequestMessage(method, $"{baseUrl}{path}");
        req.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);
        return req;
    }

    public async Task<T?> PostAsync<T>(string path, object body)
    {
        var req = NewRequest(HttpMethod.Post, path);
        req.Content = JsonContent.Create(body);
        var res = (await _http.SendAsync(req)).EnsureSuccessStatusCode();
        return await res.Content.ReadFromJsonAsync<T>();
    }

    public async Task<T?> GetAsync<T>(string path)
    {
        var req = NewRequest(HttpMethod.Get, path);
        var res = (await _http.SendAsync(req)).EnsureSuccessStatusCode();
        return await res.Content.ReadFromJsonAsync<T>();
    }

    public async Task<T?> DeleteAsync<T>(string path)
    {
        var req = NewRequest(HttpMethod.Delete, path);
        var res = (await _http.SendAsync(req)).EnsureSuccessStatusCode();
        return await res.Content.ReadFromJsonAsync<T>();
    }
}

// Kullanım
var client = new OcoOrderClient("tw_live_your_api_key_here");

var group = await client.PostAsync<ApiResponse<OcoOrderDto>>(
    "/api/v1/oco-orders",
    new CreateOcoGroupRequest(
        "TradeWiseYatirim", "123456", "EREGL",
        StopLossPrice: 21.00m,
        StopLossQuantity: 100,
        TakeProfitItems: [
            new(22.20m, 40),
            new(23.00m, 40),
            new(24.00m, 20)
        ]));

Console.WriteLine($"Grup oluşturuldu: GroupId={group!.Data.Id}");

var orders = await client.GetAsync<ApiResponse<List<OcoOrderDto>>>(
    "/api/v1/oco-orders?brokerageCode=TradeWiseYatirim&accountNumber=123456");

// Grupları grupId'ye göre organize et
var groups = orders!.Data.GroupBy(o => o.GroupId);
foreach (var g in groups)
{
    var sl = g.First(o => o.OrderType == 2);
    var tps = g.Where(o => o.OrderType == 1).ToList();
    Console.WriteLine($"Grup {g.Key}: SL={sl.Price}, TP'ler={string.Join(", ", tps.Select(t => t.Price))}");
}