19 - PlaceOrder Call Flow

Overview

The PlaceOrder API is the core order execution endpoint in OpenAlgo. It handles order validation, authentication, broker routing, and response processing through multiple layers.

Complete Flow Diagram

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        PlaceOrder Complete Flow                               β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

  Client Request (JSON)
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Layer 1: REST API Endpoint                                                  β”‚
β”‚  POST /api/v1/placeorder                                                     β”‚
β”‚                                                                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                                         β”‚
β”‚  β”‚ Rate Limiting   │──> 10 per second (default)                             β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                                         β”‚
β”‚           β”‚                                                                  β”‚
β”‚           β–Ό                                                                  β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                                                         β”‚
β”‚  β”‚ Extract apikey  β”‚                                                         β”‚
β”‚  β”‚ from request    β”‚                                                         β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
            β”‚
            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Layer 2: Service Layer (place_order_service.py)                             β”‚
β”‚                                                                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  Step 1: Order Routing Check                                         β”‚    β”‚
β”‚  β”‚                                                                      β”‚    β”‚
β”‚  β”‚  should_route_to_pending(api_key, 'placeorder')                     β”‚    β”‚
β”‚  β”‚         β”‚                                                            β”‚    β”‚
β”‚  β”‚    β”Œβ”€β”€β”€β”€β”΄β”€β”€β”€β”€β”                                                       β”‚    β”‚
β”‚  β”‚    β”‚         β”‚                                                       β”‚    β”‚
β”‚  β”‚  semi_auto  auto                                                     β”‚    β”‚
β”‚  β”‚    β”‚         β”‚                                                       β”‚    β”‚
β”‚  β”‚    β–Ό         β–Ό                                                       β”‚    β”‚
β”‚  β”‚  Queue to  Continue                                                  β”‚    β”‚
β”‚  β”‚  Action    with flow                                                 β”‚    β”‚
β”‚  β”‚  Center                                                              β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                                                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  Step 2: Order Validation                                            β”‚    β”‚
β”‚  β”‚                                                                      β”‚    β”‚
β”‚  β”‚  validate_order_data(data)                                          β”‚    β”‚
β”‚  β”‚  - Check mandatory fields                                            β”‚    β”‚
β”‚  β”‚  - Validate exchange (NSE, NFO, MCX, etc.)                          β”‚    β”‚
β”‚  β”‚  - Validate action (BUY, SELL)                                      β”‚    β”‚
β”‚  β”‚  - Validate pricetype (MARKET, LIMIT, SL, SL-M)                     β”‚    β”‚
β”‚  β”‚  - Validate product (CNC, MIS, NRML)                                β”‚    β”‚
β”‚  β”‚  - Schema validation (quantity > 0, price >= 0)                     β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                                                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  Step 3: Analyzer Mode Check                                         β”‚    β”‚
β”‚  β”‚                                                                      β”‚    β”‚
β”‚  β”‚  if get_analyze_mode() == True:                                     β”‚    β”‚
β”‚  β”‚      β†’ Route to sandbox_place_order()                               β”‚    β”‚
β”‚  β”‚      β†’ Virtual trading with β‚Ή1 Crore capital                        β”‚    β”‚
β”‚  β”‚  else:                                                              β”‚    β”‚
β”‚  β”‚      β†’ Continue to live broker                                      β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
            β”‚
            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Layer 3: Authentication (auth_db.py)                                        β”‚
β”‚                                                                              β”‚
β”‚  get_auth_token_broker(api_key)                                              β”‚
β”‚                                                                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  1. Check invalid key cache (5-min TTL)                              β”‚    β”‚
β”‚  β”‚     └─ Fast rejection of known bad keys                             β”‚    β”‚
β”‚  β”‚                                                                      β”‚    β”‚
β”‚  β”‚  2. Check verified key cache (10-hour TTL)                           β”‚    β”‚
β”‚  β”‚     └─ Fast path for legitimate requests                            β”‚    β”‚
β”‚  β”‚                                                                      β”‚    β”‚
β”‚  β”‚  3. Database lookup with Argon2 verification                         β”‚    β”‚
β”‚  β”‚     └─ api_key + API_KEY_PEPPER β†’ hash compare                      β”‚    β”‚
β”‚  β”‚                                                                      β”‚    β”‚
β”‚  β”‚  4. Decrypt auth token (Fernet)                                      β”‚    β”‚
β”‚  β”‚     └─ Get broker name, verify not revoked                          β”‚    β”‚
β”‚  β”‚                                                                      β”‚    β”‚
β”‚  β”‚  Returns: (auth_token, broker_name) or (None, None)                  β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
            β”‚
            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Layer 4: Broker Module (Dynamic Import)                                     β”‚
β”‚                                                                              β”‚
β”‚  import_broker_module(broker_name)                                           β”‚
β”‚  β†’ broker.{name}.api.order_api                                               β”‚
β”‚                                                                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  broker_module.place_order_api(order_data, auth_token)               β”‚    β”‚
β”‚  β”‚                                                                      β”‚    β”‚
β”‚  β”‚  A. Transform Data                                                   β”‚    β”‚
β”‚  β”‚     OpenAlgo Format β†’ Broker Format                                  β”‚    β”‚
β”‚  β”‚                                                                      β”‚    β”‚
β”‚  β”‚     Input:                          Output:                          β”‚    β”‚
β”‚  β”‚     {"symbol": "SBIN",              {"tradingsymbol": "SBIN-EQ",    β”‚    β”‚
β”‚  β”‚      "exchange": "NSE",              "exchange": "NSE",              β”‚    β”‚
β”‚  β”‚      "action": "BUY",                "transaction_type": "BUY",      β”‚    β”‚
β”‚  β”‚      "quantity": 100,                "quantity": 100,                β”‚    β”‚
β”‚  β”‚      "pricetype": "MARKET",          "order_type": "MARKET",         β”‚    β”‚
β”‚  β”‚      "product": "MIS"}               "product": "MIS"}               β”‚    β”‚
β”‚  β”‚                                                                      β”‚    β”‚
β”‚  β”‚  B. Symbol Mapping                                                   β”‚    β”‚
β”‚  β”‚     get_br_symbol(symbol, exchange)                                  β”‚    β”‚
β”‚  β”‚     "SBIN" β†’ "SBIN-EQ" (Zerodha)                                    β”‚    β”‚
β”‚  β”‚     "NIFTY21JAN2521500CE" β†’ broker-specific format                  β”‚    β”‚
β”‚  β”‚                                                                      β”‚    β”‚
β”‚  β”‚  C. HTTP Request to Broker API                                       β”‚    β”‚
β”‚  β”‚     POST https://api.broker.com/orders                              β”‚    β”‚
β”‚  β”‚     Headers: Authorization, API keys                                 β”‚    β”‚
β”‚  β”‚                                                                      β”‚    β”‚
β”‚  β”‚  D. Response Processing                                              β”‚    β”‚
β”‚  β”‚     Parse response, extract order_id                                 β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
            β”‚
            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Layer 5: Response Handling                                                  β”‚
β”‚                                                                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                      β”‚
β”‚  β”‚   Status 200       β”‚         β”‚   Status != 200    β”‚                      β”‚
β”‚  β”‚   (Success)        β”‚         β”‚   (Error)          β”‚                      β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                      β”‚
β”‚            β”‚                              β”‚                                  β”‚
β”‚            β–Ό                              β–Ό                                  β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                         β”‚
β”‚  β”‚ Extract order_id β”‚          β”‚ Extract error    β”‚                         β”‚
β”‚  β”‚ Emit SocketIO    β”‚          β”‚ message          β”‚                         β”‚
β”‚  β”‚ Log order async  β”‚          β”‚ Log failure      β”‚                         β”‚
β”‚  β”‚ Telegram alert   β”‚          β”‚ Return error     β”‚                         β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                         β”‚
β”‚                                                                              β”‚
β”‚  Success Response:              Error Response:                              β”‚
β”‚  {                              {                                            β”‚
β”‚    "status": "success",           "status": "error",                         β”‚
β”‚    "orderid": "123456789"         "message": "Insufficient margin"           β”‚
β”‚  }                              }                                            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Request Format

Basic Order Request

Limit Order

Stop-Loss Order

Validation Rules

Mandatory Fields

Field
Type
Description

apikey

string

OpenAlgo API key

strategy

string

Strategy identifier

symbol

string

Trading symbol

exchange

string

Exchange code

action

string

BUY or SELL

quantity

integer

Order quantity (β‰₯1)

Valid Values

Order Routing Modes

Auto Mode (Default)

Orders are executed immediately without manual intervention.

Semi-Auto Mode

Orders require manual approval before execution.

Analyzer Mode (Sandbox)

When analyze_mode = True:

Broker Integration

Dynamic Module Loading

Broker-Specific Implementation

Each broker implements:

Error Handling

Error
HTTP Code
Response

Missing field

400

{"status": "error", "message": "Missing mandatory field(s): symbol"}

Invalid exchange

400

{"status": "error", "message": "Invalid exchange"}

Invalid API key

403

{"status": "error", "message": "Invalid openalgo apikey"}

Broker not found

404

{"status": "error", "message": "Broker module not found"}

Broker API error

500

{"status": "error", "message": "Failed to place order"}

Rate limit

429

Rate limiter response

Async Operations

Order Logging

SocketIO Events

Telegram Alerts

Security Layers

API Key Verification

Request Sanitization

  • API keys removed from logs

  • Sensitive data encrypted at rest

  • Rate limiting per endpoint

Performance Optimizations

Optimization
Description

Connection pooling

HTTP clients reuse connections

API key caching

Reduce Argon2 hashing overhead

Async logging

Non-blocking order logs

Thread pool

10 worker threads for async ops

Key Files Reference

File
Purpose

restx_api/place_order.py

REST endpoint

services/place_order_service.py

Core logic

services/order_router_service.py

Semi-auto routing

services/sandbox_service.py

Analyzer mode

database/auth_db.py

Authentication

broker/{name}/api/order_api.py

Broker implementation

broker/{name}/mapping/transform_data.py

Data transformation

database/apilog_db.py

Order logging

Last updated