DhanHQ 2.1.5 → 2.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/GUIDE.md +215 -73
- data/README.md +416 -132
- data/README1.md +267 -26
- data/docs/live_order_updates.md +319 -0
- data/docs/rails_websocket_integration.md +847 -0
- data/docs/standalone_ruby_websocket_integration.md +1588 -0
- data/docs/websocket_integration.md +871 -0
- data/examples/comprehensive_websocket_examples.rb +148 -0
- data/examples/instrument_finder_test.rb +195 -0
- data/examples/live_order_updates.rb +118 -0
- data/examples/market_depth_example.rb +144 -0
- data/examples/market_feed_example.rb +81 -0
- data/examples/order_update_example.rb +105 -0
- data/examples/trading_fields_example.rb +215 -0
- data/lib/DhanHQ/configuration.rb +16 -1
- data/lib/DhanHQ/contracts/expired_options_data_contract.rb +103 -0
- data/lib/DhanHQ/contracts/trade_contract.rb +70 -0
- data/lib/DhanHQ/errors.rb +2 -0
- data/lib/DhanHQ/models/expired_options_data.rb +331 -0
- data/lib/DhanHQ/models/instrument.rb +96 -2
- data/lib/DhanHQ/models/order_update.rb +235 -0
- data/lib/DhanHQ/models/trade.rb +118 -31
- data/lib/DhanHQ/resources/expired_options_data.rb +22 -0
- data/lib/DhanHQ/version.rb +1 -1
- data/lib/DhanHQ/ws/base_connection.rb +249 -0
- data/lib/DhanHQ/ws/connection.rb +2 -2
- data/lib/DhanHQ/ws/decoder.rb +3 -3
- data/lib/DhanHQ/ws/market_depth/client.rb +376 -0
- data/lib/DhanHQ/ws/market_depth/decoder.rb +131 -0
- data/lib/DhanHQ/ws/market_depth.rb +74 -0
- data/lib/DhanHQ/ws/orders/client.rb +175 -11
- data/lib/DhanHQ/ws/orders/connection.rb +40 -81
- data/lib/DhanHQ/ws/orders.rb +28 -0
- data/lib/DhanHQ/ws/segments.rb +18 -2
- data/lib/DhanHQ/ws.rb +3 -2
- data/lib/dhan_hq.rb +5 -0
- metadata +35 -1
data/README1.md
CHANGED
@@ -423,40 +423,281 @@ end
|
|
423
423
|
|
424
424
|
---
|
425
425
|
|
426
|
-
## Super Orders
|
426
|
+
## Super Orders
|
427
427
|
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
428
|
+
Super orders are built for smart execution. They bundle entry, target, and stop-loss legs (with optional trailing jump) into one atomic request so the broker manages risk for you.
|
429
|
+
|
430
|
+
The gem exposes all related REST endpoints so you can create, modify, cancel, and list super orders programmatically across exchanges and segments.
|
431
|
+
|
432
|
+
### Endpoints
|
433
|
+
|
434
|
+
| Method | Path | Description |
|
435
|
+
| --- | --- | --- |
|
436
|
+
| `POST` | `/super/orders` | Create a new super order |
|
437
|
+
| `PUT` | `/super/orders/{order_id}` | Modify a pending super order |
|
438
|
+
| `DELETE` | `/super/orders/{order_id}/{order_leg}` | Cancel a pending super order leg |
|
439
|
+
| `GET` | `/super/orders` | Retrieve the list of all super orders |
|
440
|
+
|
441
|
+
### Place Super Order
|
442
|
+
|
443
|
+
Use this endpoint to create a new super order consisting of entry, target, stop-loss, and optional trailing jump. It is available for intraday, carry-forward, and MTF across supported exchanges.
|
444
|
+
|
445
|
+
> ℹ️ Static IP whitelisting with Dhan support is required before invoking this API.
|
446
|
+
|
447
|
+
```bash
|
448
|
+
curl --request POST \
|
449
|
+
--url https://api.dhan.co/v2/super/orders \
|
450
|
+
--header 'Content-Type: application/json' \
|
451
|
+
--header 'access-token: JWT' \
|
452
|
+
--data '{Request JSON}'
|
453
|
+
```
|
454
|
+
|
455
|
+
#### Request body
|
456
|
+
|
457
|
+
```json
|
458
|
+
{
|
459
|
+
"dhan_client_id": "1000000003",
|
460
|
+
"correlation_id": "123abc678",
|
461
|
+
"transaction_type": "BUY",
|
462
|
+
"exchange_segment": "NSE_EQ",
|
463
|
+
"product_type": "CNC",
|
464
|
+
"order_type": "LIMIT",
|
465
|
+
"security_id": "11536",
|
466
|
+
"quantity": 5,
|
467
|
+
"price": 1500,
|
468
|
+
"target_price": 1600,
|
469
|
+
"stop_loss_price": 1400,
|
470
|
+
"trailing_jump": 10
|
438
471
|
}
|
472
|
+
```
|
439
473
|
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
).
|
474
|
+
#### Parameters
|
475
|
+
|
476
|
+
| Field | Type | Description |
|
477
|
+
| --- | --- | --- |
|
478
|
+
| `dhan_client_id` | string *(required)* | User specific identification generated by Dhan. When you call via `DhanHQ::Models::SuperOrder`, the gem injects your configured client id so you can omit the key in Ruby. |
|
479
|
+
| `correlation_id` | string | Caller supplied identifier for tracking |
|
480
|
+
| `transaction_type` | enum string *(required)* | Trading side. `BUY` or `SELL`. |
|
481
|
+
| `exchange_segment` | enum string *(required)* | Exchange segment (see appendix). |
|
482
|
+
| `product_type` | enum string *(required)* | Product type. `CNC`, `INTRADAY`, `MARGIN`, or `MTF`. |
|
483
|
+
| `order_type` | enum string *(required)* | Order type. `LIMIT` or `MARKET`. |
|
484
|
+
| `security_id` | string *(required)* | Exchange standard security identifier. |
|
485
|
+
| `quantity` | integer *(required)* | Quantity for the entry leg. |
|
486
|
+
| `price` | float *(required)* | Entry price. |
|
487
|
+
| `target_price` | float *(required)* | Target price for the super order. |
|
488
|
+
| `stop_loss_price` | float *(required)* | Stop-loss price for the super order. |
|
489
|
+
| `trailing_jump` | float *(required)* | Price jump size for trailing stop-loss. |
|
490
|
+
|
491
|
+
> 🐍 When you call `DhanHQ::Models::SuperOrder.create`, supply snake_case keys exactly as shown. The client automatically camelizes
|
492
|
+
> them before submitting to Dhan's REST API and injects your configured `dhan_client_id`, allowing you to omit the key in Ruby code.
|
493
|
+
|
494
|
+
#### Response
|
495
|
+
|
496
|
+
```json
|
497
|
+
{
|
498
|
+
"order_id": "112111182198",
|
499
|
+
"order_status": "PENDING"
|
500
|
+
}
|
448
501
|
```
|
449
502
|
|
450
|
-
|
503
|
+
| Field | Type | Description |
|
504
|
+
| --- | --- | --- |
|
505
|
+
| `order_id` | string | Order identifier generated by Dhan |
|
506
|
+
| `order_status` | enum string | Latest status. `TRANSIT`, `PENDING`, or `REJECTED`. |
|
451
507
|
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
508
|
+
### Modify Super Order
|
509
|
+
|
510
|
+
Modify any leg while the order is `PENDING` or `PART_TRADED`. Once the entry leg trades fully, only the target and stop-loss legs (price and trailing jump) remain editable.
|
511
|
+
|
512
|
+
> ℹ️ Static IP whitelisting with Dhan support is required before invoking this API.
|
513
|
+
|
514
|
+
```bash
|
515
|
+
curl --request PUT \
|
516
|
+
--url https://api.dhan.co/v2/super/orders/{order_id} \
|
517
|
+
--header 'Content-Type: application/json' \
|
518
|
+
--header 'access-token: JWT' \
|
519
|
+
--data '{Request JSON}'
|
520
|
+
```
|
521
|
+
|
522
|
+
#### Request body
|
523
|
+
|
524
|
+
```json
|
525
|
+
{
|
526
|
+
"dhan_client_id": "1000000009",
|
527
|
+
"order_id": "112111182045",
|
528
|
+
"order_type": "LIMIT",
|
529
|
+
"leg_name": "ENTRY_LEG",
|
530
|
+
"quantity": 40,
|
531
|
+
"price": 1300,
|
532
|
+
"target_price": 1450,
|
533
|
+
"stop_loss_price": 1350,
|
534
|
+
"trailing_jump": 20
|
535
|
+
}
|
458
536
|
```
|
459
537
|
|
538
|
+
#### Parameters
|
539
|
+
|
540
|
+
| Field | Type | Description |
|
541
|
+
| --- | --- | --- |
|
542
|
+
| `dhan_client_id` | string *(required)* | User specific identification generated by Dhan. Automatically merged when using the Ruby model helpers. |
|
543
|
+
| `order_id` | string *(required)* | Super order identifier generated by Dhan. |
|
544
|
+
| `order_type` | enum string *(conditionally required)* | `LIMIT` or `MARKET`. Required when changing `ENTRY_LEG`. |
|
545
|
+
| `leg_name` | enum string *(required)* | `ENTRY_LEG`, `TARGET_LEG`, or `STOP_LOSS_LEG`. Entry edits allowed only while status is `PENDING` or `PART_TRADED`. |
|
546
|
+
| `quantity` | integer *(conditionally required)* | Quantity update for `ENTRY_LEG`. |
|
547
|
+
| `price` | float *(conditionally required)* | Entry price update for `ENTRY_LEG`. |
|
548
|
+
| `target_price` | float *(conditionally required)* | Target price update for `ENTRY_LEG` or `TARGET_LEG`. |
|
549
|
+
| `stop_loss_price` | float *(conditionally required)* | Stop-loss price update for `ENTRY_LEG` or `STOP_LOSS_LEG`. |
|
550
|
+
| `trailing_jump` | float *(conditionally required)* | Trailing jump update for `ENTRY_LEG` or `STOP_LOSS_LEG`. Omit or set to `0` to cancel trailing. |
|
551
|
+
|
552
|
+
#### Response
|
553
|
+
|
554
|
+
```json
|
555
|
+
{
|
556
|
+
"order_id": "112111182045",
|
557
|
+
"order_status": "TRANSIT"
|
558
|
+
}
|
559
|
+
```
|
560
|
+
|
561
|
+
| Field | Type | Description |
|
562
|
+
| --- | --- | --- |
|
563
|
+
| `order_id` | string | Order identifier generated by Dhan |
|
564
|
+
| `order_status` | enum string | Latest status. `TRANSIT`, `PENDING`, `REJECTED`, or `TRADED`. |
|
565
|
+
|
566
|
+
### Cancel Super Order
|
567
|
+
|
568
|
+
Cancel a pending or active super order leg with the order ID. Cancelling the entry leg removes all legs. Cancelling an individual target or stop-loss leg removes only that leg and it cannot be recreated on the same order.
|
569
|
+
|
570
|
+
> ℹ️ Static IP whitelisting with Dhan support is required before invoking this API.
|
571
|
+
|
572
|
+
```bash
|
573
|
+
curl --request DELETE \
|
574
|
+
--url https://api.dhan.co/v2/super/orders/{order_id}/{order_leg} \
|
575
|
+
--header 'Content-Type: application/json' \
|
576
|
+
--header 'access-token: JWT'
|
577
|
+
```
|
578
|
+
|
579
|
+
#### Path parameters
|
580
|
+
|
581
|
+
| Field | Description | Example |
|
582
|
+
| --- | --- | --- |
|
583
|
+
| `order_id` | Super order identifier. | `11211182198` |
|
584
|
+
| `order_leg` | Leg to cancel. `ENTRY_LEG`, `TARGET_LEG`, or `STOP_LOSS_LEG`. | `ENTRY_LEG` |
|
585
|
+
|
586
|
+
#### Response
|
587
|
+
|
588
|
+
```json
|
589
|
+
{
|
590
|
+
"order_id": "112111182045",
|
591
|
+
"order_status": "CANCELLED"
|
592
|
+
}
|
593
|
+
```
|
594
|
+
|
595
|
+
| Field | Type | Description |
|
596
|
+
| --- | --- | --- |
|
597
|
+
| `order_id` | string | Order identifier generated by Dhan |
|
598
|
+
| `order_status` | enum string | Latest status. `TRANSIT`, `PENDING`, `REJECTED`, or `CANCELLED`. |
|
599
|
+
|
600
|
+
### Super Order List
|
601
|
+
|
602
|
+
Fetch all super orders placed during the trading day. The response nests leg details under the entry leg, and each leg is also available in the standard order book.
|
603
|
+
|
604
|
+
```bash
|
605
|
+
curl --request GET \
|
606
|
+
--url https://api.dhan.co/v2/super/orders \
|
607
|
+
--header 'Content-Type: application/json' \
|
608
|
+
--header 'access-token: JWT'
|
609
|
+
```
|
610
|
+
|
611
|
+
#### Response
|
612
|
+
|
613
|
+
```json
|
614
|
+
[
|
615
|
+
{
|
616
|
+
"dhan_client_id": "1100003626",
|
617
|
+
"order_id": "5925022734212",
|
618
|
+
"correlation_id": "string",
|
619
|
+
"order_status": "PENDING",
|
620
|
+
"transaction_type": "BUY",
|
621
|
+
"exchange_segment": "NSE_EQ",
|
622
|
+
"product_type": "CNC",
|
623
|
+
"order_type": "LIMIT",
|
624
|
+
"validity": "DAY",
|
625
|
+
"trading_symbol": "HDFCBANK",
|
626
|
+
"security_id": "1333",
|
627
|
+
"quantity": 10,
|
628
|
+
"remaining_quantity": 10,
|
629
|
+
"ltp": 1660.95,
|
630
|
+
"price": 1500,
|
631
|
+
"after_market_order": false,
|
632
|
+
"leg_name": "ENTRY_LEG",
|
633
|
+
"exchange_order_id": "11925022734212",
|
634
|
+
"create_time": "2025-02-27 19:09:42",
|
635
|
+
"update_time": "2025-02-27 19:09:42",
|
636
|
+
"exchange_time": "2025-02-27 19:09:42",
|
637
|
+
"oms_error_description": "",
|
638
|
+
"average_traded_price": 0,
|
639
|
+
"filled_qty": 0,
|
640
|
+
"leg_details": [
|
641
|
+
{
|
642
|
+
"order_id": "5925022734212",
|
643
|
+
"leg_name": "STOP_LOSS_LEG",
|
644
|
+
"transaction_type": "SELL",
|
645
|
+
"total_quantity": 0,
|
646
|
+
"remaining_quantity": 0,
|
647
|
+
"triggered_quantity": 0,
|
648
|
+
"price": 1400,
|
649
|
+
"order_status": "PENDING",
|
650
|
+
"trailing_jump": 10
|
651
|
+
},
|
652
|
+
{
|
653
|
+
"order_id": "5925022734212",
|
654
|
+
"leg_name": "TARGET_LEG",
|
655
|
+
"transaction_type": "SELL",
|
656
|
+
"remaining_quantity": 0,
|
657
|
+
"triggered_quantity": 0,
|
658
|
+
"price": 1550,
|
659
|
+
"order_status": "PENDING",
|
660
|
+
"trailing_jump": 0
|
661
|
+
}
|
662
|
+
]
|
663
|
+
}
|
664
|
+
]
|
665
|
+
```
|
666
|
+
|
667
|
+
#### Parameters
|
668
|
+
|
669
|
+
| Field | Type | Description |
|
670
|
+
| --- | --- | --- |
|
671
|
+
| `dhan_client_id` | string | User specific identification generated by Dhan. |
|
672
|
+
| `order_id` | string | Order identifier generated by Dhan. |
|
673
|
+
| `correlation_id` | string | Caller supplied correlation identifier. |
|
674
|
+
| `order_status` | enum string | Latest status. `TRANSIT`, `PENDING`, `CLOSED`, `REJECTED`, `CANCELLED`, `PART_TRADED`, or `TRADED`. |
|
675
|
+
| `transaction_type` | enum string | Trading side. `BUY` or `SELL`. |
|
676
|
+
| `exchange_segment` | enum string | Exchange segment. |
|
677
|
+
| `product_type` | enum string | Product type. `CNC`, `INTRADAY`, `MARGIN`, or `MTF`. |
|
678
|
+
| `order_type` | enum string | Order type. `LIMIT` or `MARKET`. |
|
679
|
+
| `validity` | enum string | Order validity. `DAY`. |
|
680
|
+
| `trading_symbol` | string | Trading symbol reference. |
|
681
|
+
| `security_id` | string | Exchange security identifier. |
|
682
|
+
| `quantity` | integer | Ordered quantity. |
|
683
|
+
| `remaining_quantity` | integer | Quantity pending execution. |
|
684
|
+
| `ltp` | float | Last traded price. |
|
685
|
+
| `price` | float | Order price. |
|
686
|
+
| `after_market_order` | boolean | Indicates if order was placed after market hours. |
|
687
|
+
| `leg_name` | enum string | Leg identifier: `ENTRY_LEG`, `TARGET_LEG`, or `STOP_LOSS_LEG`. |
|
688
|
+
| `trailing_jump` | float | Trailing jump for stop-loss. |
|
689
|
+
| `exchange_order_id` | string | Exchange generated identifier. |
|
690
|
+
| `create_time` | string | Order creation timestamp. |
|
691
|
+
| `update_time` | string | Latest update timestamp. |
|
692
|
+
| `exchange_time` | string | Exchange timestamp. |
|
693
|
+
| `oms_error_description` | string | OMS error description when applicable. |
|
694
|
+
| `average_traded_price` | float | Average traded price. |
|
695
|
+
| `filled_qty` | integer | Quantity traded on the exchange. |
|
696
|
+
| `triggered_quantity` | integer | Quantity triggered for stop-loss or target legs. |
|
697
|
+
| `leg_details` | array | Nested leg details for the super order. |
|
698
|
+
|
699
|
+
> ✅ `CLOSED` indicates the entry leg and either target or stop-loss completed for the full quantity. `TRIGGERED` appears on target and stop-loss legs to highlight which one fired; inspect `triggered_quantity` for executed quantity.
|
700
|
+
|
460
701
|
---
|
461
702
|
|
462
703
|
## Packet parsing (for reference)
|
@@ -0,0 +1,319 @@
|
|
1
|
+
# Live Order Updates - Comprehensive Guide
|
2
|
+
|
3
|
+
The DhanHQ Ruby client provides comprehensive real-time order update functionality via WebSocket, covering all order states as per the [DhanHQ API documentation](https://dhanhq.co/docs/v2).
|
4
|
+
|
5
|
+
## Features
|
6
|
+
|
7
|
+
✅ **Complete Order State Tracking** - All order statuses (TRANSIT, PENDING, REJECTED, CANCELLED, TRADED, EXPIRED)
|
8
|
+
✅ **Real-time Execution Updates** - Track partial and full executions
|
9
|
+
✅ **Order State Management** - Query orders by status, symbol, execution state
|
10
|
+
✅ **Event-driven Architecture** - Subscribe to specific order events
|
11
|
+
✅ **Super Order Support** - Track entry, stop-loss, and target legs
|
12
|
+
✅ **Comprehensive Order Data** - All fields from API documentation
|
13
|
+
|
14
|
+
## Quick Start
|
15
|
+
|
16
|
+
### Basic Usage
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
require 'dhan_hq'
|
20
|
+
|
21
|
+
# Configure credentials
|
22
|
+
DhanHQ.configure do |config|
|
23
|
+
config.client_id = "your_client_id"
|
24
|
+
config.access_token = "your_access_token"
|
25
|
+
end
|
26
|
+
|
27
|
+
# Simple order update monitoring
|
28
|
+
DhanHQ::WS::Orders.connect do |order_update|
|
29
|
+
puts "Order Update: #{order_update.symbol} - #{order_update.status}"
|
30
|
+
puts "Quantity: #{order_update.traded_qty}/#{order_update.quantity}"
|
31
|
+
end
|
32
|
+
```
|
33
|
+
|
34
|
+
### Advanced Usage with Event Handlers
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
# Create client with multiple event handlers
|
38
|
+
client = DhanHQ::WS::Orders.connect_with_handlers({
|
39
|
+
:update => ->(order) { puts "Order updated: #{order.order_no}" },
|
40
|
+
:status_change => ->(data) {
|
41
|
+
puts "Status changed: #{data[:previous_status]} -> #{data[:new_status]}"
|
42
|
+
},
|
43
|
+
:execution => ->(data) {
|
44
|
+
puts "Execution: #{data[:new_traded_qty]} shares at #{data[:order_update].avg_traded_price}"
|
45
|
+
},
|
46
|
+
:order_traded => ->(order) { puts "Order fully executed: #{order.order_no}" },
|
47
|
+
:order_rejected => ->(order) { puts "Order rejected: #{order.reason_description}" }
|
48
|
+
})
|
49
|
+
|
50
|
+
# Keep the connection alive
|
51
|
+
sleep
|
52
|
+
```
|
53
|
+
|
54
|
+
## Order Update Model
|
55
|
+
|
56
|
+
The `OrderUpdate` model provides comprehensive access to all order fields:
|
57
|
+
|
58
|
+
### Order Information
|
59
|
+
```ruby
|
60
|
+
order_update.order_no # Order number
|
61
|
+
order_update.exch_order_no # Exchange order number
|
62
|
+
order_update.symbol # Trading symbol
|
63
|
+
order_update.display_name # Instrument display name
|
64
|
+
order_update.security_id # Security ID
|
65
|
+
order_update.correlation_id # User correlation ID
|
66
|
+
```
|
67
|
+
|
68
|
+
### Order Details
|
69
|
+
```ruby
|
70
|
+
order_update.txn_type # "B" for Buy, "S" for Sell
|
71
|
+
order_update.order_type # "LMT", "MKT", "SL", "SLM"
|
72
|
+
order_update.product # "C", "I", "M", "F", "V", "B"
|
73
|
+
order_update.validity # "DAY", "IOC"
|
74
|
+
order_update.status # "TRANSIT", "PENDING", "REJECTED", etc.
|
75
|
+
```
|
76
|
+
|
77
|
+
### Execution Information
|
78
|
+
```ruby
|
79
|
+
order_update.quantity # Total order quantity
|
80
|
+
order_update.traded_qty # Executed quantity
|
81
|
+
order_update.remaining_quantity # Pending quantity
|
82
|
+
order_update.price # Order price
|
83
|
+
order_update.traded_price # Last trade price
|
84
|
+
order_update.avg_traded_price # Average execution price
|
85
|
+
```
|
86
|
+
|
87
|
+
### Helper Methods
|
88
|
+
|
89
|
+
#### Transaction Type
|
90
|
+
```ruby
|
91
|
+
order_update.buy? # true if BUY order
|
92
|
+
order_update.sell? # true if SELL order
|
93
|
+
```
|
94
|
+
|
95
|
+
#### Order Type
|
96
|
+
```ruby
|
97
|
+
order_update.limit_order? # true if LIMIT order
|
98
|
+
order_update.market_order? # true if MARKET order
|
99
|
+
order_update.stop_loss_order? # true if STOP LOSS order
|
100
|
+
```
|
101
|
+
|
102
|
+
#### Product Type
|
103
|
+
```ruby
|
104
|
+
order_update.cnc_product? # true if CNC
|
105
|
+
order_update.intraday_product? # true if INTRADAY
|
106
|
+
order_update.margin_product? # true if MARGIN
|
107
|
+
order_update.mtf_product? # true if MTF
|
108
|
+
order_update.cover_order? # true if CO
|
109
|
+
order_update.bracket_order? # true if BO
|
110
|
+
```
|
111
|
+
|
112
|
+
#### Order Status
|
113
|
+
```ruby
|
114
|
+
order_update.transit? # true if TRANSIT
|
115
|
+
order_update.pending? # true if PENDING
|
116
|
+
order_update.rejected? # true if REJECTED
|
117
|
+
order_update.cancelled? # true if CANCELLED
|
118
|
+
order_update.traded? # true if TRADED
|
119
|
+
order_update.expired? # true if EXPIRED
|
120
|
+
```
|
121
|
+
|
122
|
+
#### Execution State
|
123
|
+
```ruby
|
124
|
+
order_update.partially_executed? # true if partially filled
|
125
|
+
order_update.fully_executed? # true if fully filled
|
126
|
+
order_update.not_executed? # true if not filled
|
127
|
+
order_update.execution_percentage # execution percentage (0-100)
|
128
|
+
```
|
129
|
+
|
130
|
+
#### Super Order Legs
|
131
|
+
```ruby
|
132
|
+
order_update.entry_leg? # true if entry leg (leg_no == 1)
|
133
|
+
order_update.stop_loss_leg? # true if stop-loss leg (leg_no == 2)
|
134
|
+
order_update.target_leg? # true if target leg (leg_no == 3)
|
135
|
+
order_update.super_order? # true if part of super order
|
136
|
+
```
|
137
|
+
|
138
|
+
## Client Methods
|
139
|
+
|
140
|
+
### Order Tracking
|
141
|
+
```ruby
|
142
|
+
client = DhanHQ::WS::Orders.client.start
|
143
|
+
|
144
|
+
# Get specific order state
|
145
|
+
order = client.order_state("1124091136546")
|
146
|
+
|
147
|
+
# Get all tracked orders
|
148
|
+
all_orders = client.all_orders
|
149
|
+
|
150
|
+
# Query orders by status
|
151
|
+
pending_orders = client.orders_by_status("PENDING")
|
152
|
+
traded_orders = client.orders_by_status("TRADED")
|
153
|
+
|
154
|
+
# Query orders by symbol
|
155
|
+
reliance_orders = client.orders_by_symbol("RELIANCE")
|
156
|
+
|
157
|
+
# Query by execution state
|
158
|
+
partial_orders = client.partially_executed_orders
|
159
|
+
full_orders = client.fully_executed_orders
|
160
|
+
pending_orders = client.pending_orders
|
161
|
+
```
|
162
|
+
|
163
|
+
### Event Handling
|
164
|
+
```ruby
|
165
|
+
client = DhanHQ::WS::Orders.client
|
166
|
+
|
167
|
+
# General events
|
168
|
+
client.on(:update) { |order| puts "Order updated: #{order.order_no}" }
|
169
|
+
client.on(:raw) { |msg| puts "Raw message: #{msg}" }
|
170
|
+
client.on(:close) { puts "Connection closed" }
|
171
|
+
|
172
|
+
# Status-specific events
|
173
|
+
client.on(:order_transit) { |order| puts "Order in transit: #{order.order_no}" }
|
174
|
+
client.on(:order_pending) { |order| puts "Order pending: #{order.order_no}" }
|
175
|
+
client.on(:order_rejected) { |order| puts "Order rejected: #{order.reason_description}" }
|
176
|
+
client.on(:order_cancelled) { |order| puts "Order cancelled: #{order.order_no}" }
|
177
|
+
client.on(:order_traded) { |order| puts "Order traded: #{order.order_no}" }
|
178
|
+
client.on(:order_expired) { |order| puts "Order expired: #{order.order_no}" }
|
179
|
+
|
180
|
+
# State change events
|
181
|
+
client.on(:status_change) do |data|
|
182
|
+
puts "Status: #{data[:previous_status]} -> #{data[:new_status]}"
|
183
|
+
end
|
184
|
+
|
185
|
+
client.on(:execution) do |data|
|
186
|
+
puts "Execution: #{data[:new_traded_qty]} shares (#{data[:execution_percentage]}%)"
|
187
|
+
end
|
188
|
+
|
189
|
+
client.start
|
190
|
+
```
|
191
|
+
|
192
|
+
## Configuration
|
193
|
+
|
194
|
+
### Environment Variables
|
195
|
+
```bash
|
196
|
+
# Required
|
197
|
+
CLIENT_ID=your_client_id
|
198
|
+
ACCESS_TOKEN=your_access_token
|
199
|
+
|
200
|
+
# Optional WebSocket settings
|
201
|
+
DHAN_WS_ORDER_URL=wss://api-order-update.dhan.co
|
202
|
+
DHAN_WS_USER_TYPE=SELF # or PARTNER
|
203
|
+
DHAN_PARTNER_ID=partner_id # if UserType is PARTNER
|
204
|
+
DHAN_PARTNER_SECRET=partner_secret # if UserType is PARTNER
|
205
|
+
```
|
206
|
+
|
207
|
+
### Programmatic Configuration
|
208
|
+
```ruby
|
209
|
+
DhanHQ.configure do |config|
|
210
|
+
config.client_id = "your_client_id"
|
211
|
+
config.access_token = "your_access_token"
|
212
|
+
config.ws_order_url = "wss://api-order-update.dhan.co"
|
213
|
+
config.ws_user_type = "SELF" # or "PARTNER"
|
214
|
+
|
215
|
+
# For partner mode
|
216
|
+
config.partner_id = "partner_id"
|
217
|
+
config.partner_secret = "partner_secret"
|
218
|
+
end
|
219
|
+
```
|
220
|
+
|
221
|
+
## Complete Example
|
222
|
+
|
223
|
+
```ruby
|
224
|
+
require 'dhan_hq'
|
225
|
+
|
226
|
+
# Configure
|
227
|
+
DhanHQ.configure_with_env
|
228
|
+
|
229
|
+
# Create order tracking client
|
230
|
+
client = DhanHQ::WS::Orders.client
|
231
|
+
|
232
|
+
# Set up comprehensive event handling
|
233
|
+
client.on(:update) do |order|
|
234
|
+
puts "\n=== Order Update ==="
|
235
|
+
puts "Order: #{order.order_no} | Symbol: #{order.symbol}"
|
236
|
+
puts "Status: #{order.status} | Type: #{order.txn_type}"
|
237
|
+
puts "Quantity: #{order.traded_qty}/#{order.quantity} (#{order.execution_percentage}%)"
|
238
|
+
puts "Price: #{order.price} | Avg Price: #{order.avg_traded_price}"
|
239
|
+
puts "Leg: #{order.leg_no} | Super Order: #{order.super_order?}"
|
240
|
+
end
|
241
|
+
|
242
|
+
client.on(:status_change) do |data|
|
243
|
+
order = data[:order_update]
|
244
|
+
puts "\n🔄 Status Change: #{order.order_no}"
|
245
|
+
puts " #{data[:previous_status]} -> #{data[:new_status]}"
|
246
|
+
end
|
247
|
+
|
248
|
+
client.on(:execution) do |data|
|
249
|
+
order = data[:order_update]
|
250
|
+
puts "\n💰 Execution Update: #{order.order_no}"
|
251
|
+
puts " #{data[:previous_traded_qty]} -> #{data[:new_traded_qty]} shares"
|
252
|
+
puts " Execution: #{data[:execution_percentage]}%"
|
253
|
+
end
|
254
|
+
|
255
|
+
client.on(:order_traded) do |order|
|
256
|
+
puts "\n✅ Order Fully Executed: #{order.order_no}"
|
257
|
+
puts " Symbol: #{order.symbol} | Quantity: #{order.traded_qty}"
|
258
|
+
puts " Average Price: #{order.avg_traded_price}"
|
259
|
+
end
|
260
|
+
|
261
|
+
client.on(:order_rejected) do |order|
|
262
|
+
puts "\n❌ Order Rejected: #{order.order_no}"
|
263
|
+
puts " Reason: #{order.reason_description}"
|
264
|
+
end
|
265
|
+
|
266
|
+
# Start monitoring
|
267
|
+
puts "Starting order update monitoring..."
|
268
|
+
client.start
|
269
|
+
|
270
|
+
# Keep running
|
271
|
+
begin
|
272
|
+
loop do
|
273
|
+
sleep 1
|
274
|
+
|
275
|
+
# Print order summary every 30 seconds
|
276
|
+
if Time.now.to_i % 30 == 0
|
277
|
+
puts "\n📊 Order Summary:"
|
278
|
+
puts " Total Orders: #{client.all_orders.size}"
|
279
|
+
puts " Pending: #{client.orders_by_status('PENDING').size}"
|
280
|
+
puts " Traded: #{client.orders_by_status('TRADED').size}"
|
281
|
+
puts " Rejected: #{client.orders_by_status('REJECTED').size}"
|
282
|
+
end
|
283
|
+
end
|
284
|
+
rescue Interrupt
|
285
|
+
puts "\nShutting down..."
|
286
|
+
client.stop
|
287
|
+
end
|
288
|
+
```
|
289
|
+
|
290
|
+
## Order States Covered
|
291
|
+
|
292
|
+
The implementation covers all order states as per DhanHQ API documentation:
|
293
|
+
|
294
|
+
| Status | Description | Event |
|
295
|
+
| ----------- | ---------------------------- | ------------------ |
|
296
|
+
| `TRANSIT` | Order in transit to exchange | `:order_transit` |
|
297
|
+
| `PENDING` | Order pending at exchange | `:order_pending` |
|
298
|
+
| `REJECTED` | Order rejected by exchange | `:order_rejected` |
|
299
|
+
| `CANCELLED` | Order cancelled | `:order_cancelled` |
|
300
|
+
| `TRADED` | Order fully executed | `:order_traded` |
|
301
|
+
| `EXPIRED` | Order expired | `:order_expired` |
|
302
|
+
|
303
|
+
## Error Handling
|
304
|
+
|
305
|
+
The WebSocket client includes comprehensive error handling:
|
306
|
+
|
307
|
+
- **Automatic Reconnection** with exponential backoff
|
308
|
+
- **Rate Limit Handling** with 60-second cool-off for 429 errors
|
309
|
+
- **Connection Monitoring** with health checks
|
310
|
+
- **Event Handler Protection** - errors in handlers don't crash the client
|
311
|
+
|
312
|
+
## Thread Safety
|
313
|
+
|
314
|
+
All operations are thread-safe using `Concurrent::Map` and `Concurrent::AtomicBoolean` for:
|
315
|
+
- Order state tracking
|
316
|
+
- Event callback management
|
317
|
+
- Connection state management
|
318
|
+
|
319
|
+
This ensures safe usage in multi-threaded applications.
|