DhanHQ 2.5.0 → 2.6.1

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.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +9 -1
  3. data/CHANGELOG.md +78 -6
  4. data/GUIDE.md +57 -39
  5. data/README.md +24 -23
  6. data/docs/API_DOCS_GAPS.md +128 -0
  7. data/docs/API_VERIFICATION.md +10 -11
  8. data/docs/ARCHIVE_README.md +16 -16
  9. data/docs/AUTHENTICATION.md +1 -1
  10. data/docs/CONSTANTS_REFERENCE.md +477 -0
  11. data/docs/DATA_API_PARAMETERS.md +7 -7
  12. data/docs/{rails_websocket_integration.md → RAILS_WEBSOCKET_INTEGRATION.md} +10 -10
  13. data/docs/{standalone_ruby_websocket_integration.md → STANDALONE_RUBY_WEBSOCKET_INTEGRATION.md} +32 -32
  14. data/docs/{technical_analysis.md → TECHNICAL_ANALYSIS.md} +3 -3
  15. data/docs/TESTING_GUIDE.md +84 -82
  16. data/docs/{websocket_integration.md → WEBSOCKET_INTEGRATION.md} +19 -19
  17. data/docs/WEBSOCKET_PROTOCOL.md +2 -2
  18. data/lib/DhanHQ/constants.rb +456 -151
  19. data/lib/DhanHQ/contracts/alert_order_contract.rb +37 -10
  20. data/lib/DhanHQ/contracts/base_contract.rb +22 -0
  21. data/lib/DhanHQ/contracts/edis_contract.rb +25 -0
  22. data/lib/DhanHQ/contracts/margin_calculator_contract.rb +27 -4
  23. data/lib/DhanHQ/contracts/modify_order_contract.rb +65 -12
  24. data/lib/DhanHQ/contracts/multi_scrip_margin_calc_request_contract.rb +23 -0
  25. data/lib/DhanHQ/contracts/order_contract.rb +171 -39
  26. data/lib/DhanHQ/contracts/place_order_contract.rb +14 -141
  27. data/lib/DhanHQ/contracts/pnl_based_exit_contract.rb +20 -0
  28. data/lib/DhanHQ/contracts/position_conversion_contract.rb +15 -3
  29. data/lib/DhanHQ/contracts/slice_order_contract.rb +10 -1
  30. data/lib/DhanHQ/contracts/user_ip_contract.rb +14 -0
  31. data/lib/DhanHQ/core/base_model.rb +13 -4
  32. data/lib/DhanHQ/helpers/response_helper.rb +2 -2
  33. data/lib/DhanHQ/helpers/validation_helper.rb +1 -1
  34. data/lib/DhanHQ/models/alert_order.rb +7 -11
  35. data/lib/DhanHQ/models/concerns/api_response_handler.rb +46 -0
  36. data/lib/DhanHQ/models/edis.rb +0 -9
  37. data/lib/DhanHQ/models/expired_options_data.rb +6 -12
  38. data/lib/DhanHQ/models/forever_order.rb +8 -5
  39. data/lib/DhanHQ/models/historical_data.rb +0 -8
  40. data/lib/DhanHQ/models/instrument.rb +1 -7
  41. data/lib/DhanHQ/models/instrument_helpers.rb +4 -4
  42. data/lib/DhanHQ/models/kill_switch.rb +1 -11
  43. data/lib/DhanHQ/models/margin.rb +2 -2
  44. data/lib/DhanHQ/models/order.rb +107 -126
  45. data/lib/DhanHQ/models/order_update.rb +7 -13
  46. data/lib/DhanHQ/models/pnl_exit.rb +1 -9
  47. data/lib/DhanHQ/models/position.rb +1 -1
  48. data/lib/DhanHQ/models/postback.rb +4 -13
  49. data/lib/DhanHQ/models/profile.rb +0 -10
  50. data/lib/DhanHQ/models/super_order.rb +13 -3
  51. data/lib/DhanHQ/models/trade.rb +11 -23
  52. data/lib/DhanHQ/resources/ip_setup.rb +16 -5
  53. data/lib/DhanHQ/resources/kill_switch.rb +9 -7
  54. data/lib/DhanHQ/resources/orders.rb +41 -41
  55. data/lib/DhanHQ/version.rb +1 -1
  56. data/lib/DhanHQ/ws/cmd_bus.rb +1 -1
  57. data/lib/DhanHQ/ws/orders/client.rb +6 -6
  58. data/lib/DhanHQ/ws/singleton_lock.rb +2 -1
  59. data/lib/dhanhq/analysis/options_buying_advisor.rb +2 -2
  60. data/lib/rubocop/cop/dhanhq/use_constants.rb +171 -0
  61. metadata +20 -23
  62. data/TODO-1.md +0 -14
  63. data/TODO.md +0 -127
  64. data/app/services/live/order_update_guard_support.rb +0 -75
  65. data/app/services/live/order_update_hub.rb +0 -76
  66. data/app/services/live/order_update_persistence_support.rb +0 -68
  67. data/docs/PR_2.2.0.md +0 -48
  68. data/examples/comprehensive_websocket_examples.rb +0 -148
  69. data/examples/instrument_finder_test.rb +0 -195
  70. data/examples/live_order_updates.rb +0 -118
  71. data/examples/market_depth_example.rb +0 -144
  72. data/examples/market_feed_example.rb +0 -81
  73. data/examples/order_update_example.rb +0 -105
  74. data/examples/trading_fields_example.rb +0 -215
  75. /data/docs/{live_order_updates.md → LIVE_ORDER_UPDATES.md} +0 -0
  76. /data/docs/{rails_integration.md → RAILS_INTEGRATION.md} +0 -0
@@ -43,10 +43,10 @@ market_client = DhanHQ::WS.connect(mode: :ticker) do |tick|
43
43
  end
44
44
 
45
45
  # Subscribe to major indices
46
- market_client.subscribe_one(segment: "IDX_I", security_id: "13") # NIFTY
47
- market_client.subscribe_one(segment: "IDX_I", security_id: "25") # BANKNIFTY
48
- market_client.subscribe_one(segment: "IDX_I", security_id: "29") # NIFTYIT
49
- market_client.subscribe_one(segment: "IDX_I", security_id: "51") # SENSEX
46
+ market_client.subscribe_one(segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "13") # NIFTY
47
+ market_client.subscribe_one(segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "25") # BANKNIFTY
48
+ market_client.subscribe_one(segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "29") # NIFTYIT
49
+ market_client.subscribe_one(segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "51") # SENSEX
50
50
 
51
51
  # Wait for data
52
52
  sleep(30)
@@ -179,10 +179,10 @@ class MarketFeedScript
179
179
 
180
180
  def subscribe_to_indices
181
181
  indices = [
182
- { segment: "IDX_I", security_id: "13", name: "NIFTY" },
183
- { segment: "IDX_I", security_id: "25", name: "BANKNIFTY" },
184
- { segment: "IDX_I", security_id: "29", name: "NIFTYIT" },
185
- { segment: "IDX_I", security_id: "51", name: "SENSEX" }
182
+ { segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "13", name: "NIFTY" },
183
+ { segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "25", name: "BANKNIFTY" },
184
+ { segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "29", name: "NIFTYIT" },
185
+ { segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "51", name: "SENSEX" }
186
186
  ]
187
187
 
188
188
  indices.each do |index|
@@ -411,8 +411,8 @@ class MarketDepthScript
411
411
 
412
412
  # Define symbols with correct exchange segments and security IDs
413
413
  symbols = [
414
- { symbol: "RELIANCE", exchange_segment: "NSE_EQ", security_id: "2885" },
415
- { symbol: "TCS", exchange_segment: "NSE_EQ", security_id: "11536" }
414
+ { symbol: "RELIANCE", exchange_segment: DhanHQ::Constants::ExchangeSegment::NSE_EQ, security_id: "2885" },
415
+ { symbol: "TCS", exchange_segment: DhanHQ::Constants::ExchangeSegment::NSE_EQ, security_id: "11536" }
416
416
  ]
417
417
 
418
418
  @depth_client = DhanHQ::WS::MarketDepth.connect(symbols: symbols) do |depth_data|
@@ -664,10 +664,10 @@ class MarketFeedDaemon
664
664
 
665
665
  def subscribe_to_indices
666
666
  indices = [
667
- { segment: "IDX_I", security_id: "13", name: "NIFTY" },
668
- { segment: "IDX_I", security_id: "25", name: "BANKNIFTY" },
669
- { segment: "IDX_I", security_id: "29", name: "NIFTYIT" },
670
- { segment: "IDX_I", security_id: "51", name: "SENSEX" }
667
+ { segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "13", name: "NIFTY" },
668
+ { segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "25", name: "BANKNIFTY" },
669
+ { segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "29", name: "NIFTYIT" },
670
+ { segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "51", name: "SENSEX" }
671
671
  ]
672
672
 
673
673
  indices.each do |index|
@@ -906,10 +906,10 @@ class MarketDataCLI
906
906
 
907
907
  def subscribe_to_default_indices(client)
908
908
  indices = [
909
- { segment: "IDX_I", security_id: "13", name: "NIFTY" },
910
- { segment: "IDX_I", security_id: "25", name: "BANKNIFTY" },
911
- { segment: "IDX_I", security_id: "29", name: "NIFTYIT" },
912
- { segment: "IDX_I", security_id: "51", name: "SENSEX" }
909
+ { segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "13", name: "NIFTY" },
910
+ { segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "25", name: "BANKNIFTY" },
911
+ { segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "29", name: "NIFTYIT" },
912
+ { segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "51", name: "SENSEX" }
913
913
  ]
914
914
 
915
915
  indices.each do |index|
@@ -1128,10 +1128,10 @@ class RobustWebSocketClient
1128
1128
 
1129
1129
  def subscribe_to_indices
1130
1130
  indices = [
1131
- { segment: "IDX_I", security_id: "13", name: "NIFTY" },
1132
- { segment: "IDX_I", security_id: "25", name: "BANKNIFTY" },
1133
- { segment: "IDX_I", security_id: "29", name: "NIFTYIT" },
1134
- { segment: "IDX_I", security_id: "51", name: "SENSEX" }
1131
+ { segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "13", name: "NIFTY" },
1132
+ { segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "25", name: "BANKNIFTY" },
1133
+ { segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "29", name: "NIFTYIT" },
1134
+ { segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "51", name: "SENSEX" }
1135
1135
  ]
1136
1136
 
1137
1137
  indices.each do |index|
@@ -1311,10 +1311,10 @@ class ProductionWebSocketClient
1311
1311
 
1312
1312
  def subscribe_to_indices
1313
1313
  indices = [
1314
- { segment: "IDX_I", security_id: "13", name: "NIFTY" },
1315
- { segment: "IDX_I", security_id: "25", name: "BANKNIFTY" },
1316
- { segment: "IDX_I", security_id: "29", name: "NIFTYIT" },
1317
- { segment: "IDX_I", security_id: "51", name: "SENSEX" }
1314
+ { segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "13", name: "NIFTY" },
1315
+ { segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "25", name: "BANKNIFTY" },
1316
+ { segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "29", name: "NIFTYIT" },
1317
+ { segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "51", name: "SENSEX" }
1318
1318
  ]
1319
1319
 
1320
1320
  indices.each do |index|
@@ -1461,8 +1461,8 @@ class WebSocketMonitor
1461
1461
 
1462
1462
  def start_market_depth_client
1463
1463
  symbols = [
1464
- { symbol: "RELIANCE", exchange_segment: "NSE_EQ", security_id: "2885" },
1465
- { symbol: "TCS", exchange_segment: "NSE_EQ", security_id: "11536" }
1464
+ { symbol: "RELIANCE", exchange_segment: DhanHQ::Constants::ExchangeSegment::NSE_EQ, security_id: "2885" },
1465
+ { symbol: "TCS", exchange_segment: DhanHQ::Constants::ExchangeSegment::NSE_EQ, security_id: "11536" }
1466
1466
  ]
1467
1467
 
1468
1468
  @clients[:market_depth] = DhanHQ::WS::MarketDepth.connect(symbols: symbols) do |depth_data|
@@ -1483,10 +1483,10 @@ class WebSocketMonitor
1483
1483
 
1484
1484
  def subscribe_to_indices(client)
1485
1485
  indices = [
1486
- { segment: "IDX_I", security_id: "13", name: "NIFTY" },
1487
- { segment: "IDX_I", security_id: "25", name: "BANKNIFTY" },
1488
- { segment: "IDX_I", security_id: "29", name: "NIFTYIT" },
1489
- { segment: "IDX_I", security_id: "51", name: "SENSEX" }
1486
+ { segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "13", name: "NIFTY" },
1487
+ { segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "25", name: "BANKNIFTY" },
1488
+ { segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "29", name: "NIFTYIT" },
1489
+ { segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "51", name: "SENSEX" }
1490
1490
  ]
1491
1491
 
1492
1492
  indices.each do |index|
@@ -26,8 +26,8 @@ DhanHQ.configure_with_env
26
26
 
27
27
  ta = TA::TechnicalAnalysis.new(throttle_seconds: 2.5, max_retries: 3)
28
28
  indicators = ta.compute(
29
- exchange_segment: "NSE_EQ",
30
- instrument: "EQUITY",
29
+ exchange_segment: DhanHQ::Constants::ExchangeSegment::NSE_EQ,
30
+ instrument: DhanHQ::Constants::InstrumentType::EQUITY,
31
31
  security_id: "1333",
32
32
  intervals: [1, 5, 15, 25, 60] # each fetched directly from API
33
33
  )
@@ -75,7 +75,7 @@ Example summary:
75
75
 
76
76
  ```ruby
77
77
  {
78
- meta: { security_id: "1333", instrument: "EQUITY", exchange_segment: "NSE_EQ" },
78
+ meta: { security_id: "1333", instrument: DhanHQ::Constants::InstrumentType::EQUITY, exchange_segment: DhanHQ::Constants::ExchangeSegment::NSE_EQ },
79
79
  summary: {
80
80
  bias: :bullish, # :bullish | :bearish | :neutral
81
81
  setup: :buy_on_dip, # :buy_on_dip | :sell_on_rise | :range_trade
@@ -95,10 +95,10 @@ market_client = DhanHQ::WS.connect(mode: :ticker) do |tick|
95
95
  end
96
96
 
97
97
  # Subscribe to NIFTY (Security ID: 13, Segment: IDX_I)
98
- market_client.subscribe_one(segment: "IDX_I", security_id: "13")
98
+ market_client.subscribe_one(segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "13")
99
99
 
100
100
  # Subscribe to BANKNIFTY (Security ID: 25, Segment: IDX_I)
101
- market_client.subscribe_one(segment: "IDX_I", security_id: "25")
101
+ market_client.subscribe_one(segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "25")
102
102
 
103
103
  # Wait for data (in console, you can continue working)
104
104
  sleep(10)
@@ -117,7 +117,7 @@ ohlc_client = DhanHQ::WS.connect(mode: :ohlc) do |data|
117
117
  end
118
118
 
119
119
  # Subscribe to NIFTY
120
- ohlc_client.subscribe_one(segment: "IDX_I", security_id: "13")
120
+ ohlc_client.subscribe_one(segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "13")
121
121
 
122
122
  sleep(10)
123
123
  ohlc_client.stop
@@ -135,7 +135,7 @@ quote_client = DhanHQ::WS.connect(mode: :quote) do |data|
135
135
  end
136
136
 
137
137
  # Subscribe to NIFTY
138
- quote_client.subscribe_one(segment: "IDX_I", security_id: "13")
138
+ quote_client.subscribe_one(segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "13")
139
139
 
140
140
  sleep(10)
141
141
  quote_client.stop
@@ -151,10 +151,10 @@ end
151
151
 
152
152
  # Subscribe to multiple indices
153
153
  indices = [
154
- { segment: "IDX_I", security_id: "13" }, # NIFTY
155
- { segment: "IDX_I", security_id: "25" }, # BANKNIFTY
156
- { segment: "IDX_I", security_id: "29" }, # NIFTYIT
157
- { segment: "IDX_I", security_id: "51" } # SENSEX
154
+ { segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "13" }, # NIFTY
155
+ { segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "25" }, # BANKNIFTY
156
+ { segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "29" }, # NIFTYIT
157
+ { segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "51" } # SENSEX
158
158
  ]
159
159
 
160
160
  indices.each do |idx|
@@ -169,7 +169,7 @@ market_client.stop
169
169
 
170
170
  ```ruby
171
171
  market_client = DhanHQ::WS.connect(mode: :ticker) { |tick| puts tick[:ltp] }
172
- market_client.subscribe_one(segment: "IDX_I", security_id: "13")
172
+ market_client.subscribe_one(segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "13")
173
173
 
174
174
  # Check connection state
175
175
  puts "Connected: #{market_client.connected?}"
@@ -326,11 +326,11 @@ depth_client.stop
326
326
  # Place a market order
327
327
  order = DhanHQ::Models::Order.place(
328
328
  dhan_client_id: "1000000003",
329
- transaction_type: "BUY",
330
- exchange_segment: "NSE_EQ",
331
- product_type: "INTRADAY",
332
- order_type: "MARKET",
333
- validity: "DAY",
329
+ transaction_type: DhanHQ::Constants::TransactionType::BUY,
330
+ exchange_segment: DhanHQ::Constants::ExchangeSegment::NSE_EQ,
331
+ product_type: DhanHQ::Constants::ProductType::INTRADAY,
332
+ order_type: DhanHQ::Constants::OrderType::MARKET,
333
+ validity: DhanHQ::Constants::Validity::DAY,
334
334
  security_id: "11536", # TCS
335
335
  quantity: 1
336
336
  )
@@ -345,11 +345,11 @@ puts "Status: #{order.order_status}"
345
345
  # Place a limit order
346
346
  order = DhanHQ::Models::Order.place(
347
347
  dhan_client_id: "1000000003",
348
- transaction_type: "BUY",
349
- exchange_segment: "NSE_EQ",
350
- product_type: "INTRADAY",
351
- order_type: "LIMIT",
352
- validity: "DAY",
348
+ transaction_type: DhanHQ::Constants::TransactionType::BUY,
349
+ exchange_segment: DhanHQ::Constants::ExchangeSegment::NSE_EQ,
350
+ product_type: DhanHQ::Constants::ProductType::INTRADAY,
351
+ order_type: DhanHQ::Constants::OrderType::LIMIT,
352
+ validity: DhanHQ::Constants::Validity::DAY,
353
353
  security_id: "11536",
354
354
  quantity: 1,
355
355
  price: 3500.0
@@ -364,11 +364,11 @@ puts "Order ID: #{order.order_id}"
364
364
  # Place stop loss order
365
365
  order = DhanHQ::Models::Order.place(
366
366
  dhan_client_id: "1000000003",
367
- transaction_type: "BUY",
368
- exchange_segment: "NSE_EQ",
369
- product_type: "INTRADAY",
367
+ transaction_type: DhanHQ::Constants::TransactionType::BUY,
368
+ exchange_segment: DhanHQ::Constants::ExchangeSegment::NSE_EQ,
369
+ product_type: DhanHQ::Constants::ProductType::INTRADAY,
370
370
  order_type: "STOPLOSS",
371
- validity: "DAY",
371
+ validity: DhanHQ::Constants::Validity::DAY,
372
372
  security_id: "11536",
373
373
  quantity: 1,
374
374
  price: 3500.0,
@@ -410,11 +410,11 @@ orders = DhanHQ::Models::Order.all
410
410
  puts "Total orders: #{orders.size}"
411
411
 
412
412
  # Filter pending orders
413
- pending = orders.select { |o| o.order_status == "PENDING" }
413
+ pending = orders.select { |o| o.order_status == DhanHQ::Constants::OrderStatus::PENDING }
414
414
  puts "Pending orders: #{pending.size}"
415
415
 
416
416
  # Filter executed orders
417
- executed = orders.select { |o| o.order_status == "TRADED" }
417
+ executed = orders.select { |o| o.order_status == DhanHQ::Constants::OrderStatus::TRADED }
418
418
  puts "Executed orders: #{executed.size}"
419
419
  ```
420
420
 
@@ -472,11 +472,11 @@ end
472
472
  # Create order instance
473
473
  order = DhanHQ::Models::Order.new(
474
474
  dhan_client_id: "1000000003",
475
- transaction_type: "BUY",
476
- exchange_segment: "NSE_EQ",
477
- product_type: "INTRADAY",
478
- order_type: "MARKET",
479
- validity: "DAY",
475
+ transaction_type: DhanHQ::Constants::TransactionType::BUY,
476
+ exchange_segment: DhanHQ::Constants::ExchangeSegment::NSE_EQ,
477
+ product_type: DhanHQ::Constants::ProductType::INTRADAY,
478
+ order_type: DhanHQ::Constants::OrderType::MARKET,
479
+ validity: DhanHQ::Constants::Validity::DAY,
480
480
  security_id: "11536",
481
481
  quantity: 1
482
482
  )
@@ -499,7 +499,7 @@ positions = DhanHQ::Models::Position.all
499
499
  puts "Total positions: #{positions.size}"
500
500
 
501
501
  # Filter by exchange
502
- nse_positions = positions.select { |p| p.exchange_segment == "NSE_EQ" }
502
+ nse_positions = positions.select { |p| p.exchange_segment == DhanHQ::Constants::ExchangeSegment::NSE_EQ }
503
503
  puts "NSE positions: #{nse_positions.size}"
504
504
 
505
505
  # Filter long positions
@@ -517,8 +517,8 @@ position = DhanHQ::Models::Position.all.first
517
517
  if position
518
518
  result = position.convert(
519
519
  dhan_client_id: "1000000003",
520
- from_product_type: "INTRADAY",
521
- to_product_type: "MARGIN",
520
+ from_product_type: DhanHQ::Constants::ProductType::INTRADAY,
521
+ to_product_type: DhanHQ::Constants::ProductType::MARGIN,
522
522
  quantity: position.net_qty.abs
523
523
  )
524
524
 
@@ -677,7 +677,7 @@ puts " Ask Price: ₹#{quote_data[:ask_price]}"
677
677
  # Get daily candles
678
678
  historical_data = DhanHQ::Models::HistoricalData.daily(
679
679
  security_id: "11536",
680
- exchange_segment: "NSE_EQ",
680
+ exchange_segment: DhanHQ::Constants::ExchangeSegment::NSE_EQ,
681
681
  from_date: Date.today - 30,
682
682
  to_date: Date.today
683
683
  )
@@ -694,7 +694,7 @@ end
694
694
  # Get intraday candles (5-minute interval)
695
695
  historical_data = DhanHQ::Models::HistoricalData.intraday(
696
696
  security_id: "11536",
697
- exchange_segment: "NSE_EQ",
697
+ exchange_segment: DhanHQ::Constants::ExchangeSegment::NSE_EQ,
698
698
  from_date: Date.today,
699
699
  to_date: Date.today,
700
700
  interval: 5
@@ -714,7 +714,7 @@ end
714
714
  # Get expiry list for NIFTY
715
715
  expiry_list = DhanHQ::Models::OptionChain.fetch_expiry_list(
716
716
  underlying_scrip: "NIFTY",
717
- underlying_seg: "IDX_I"
717
+ underlying_seg: DhanHQ::Constants::ExchangeSegment::IDX_I
718
718
  )
719
719
 
720
720
  puts "Available expiries:"
@@ -731,7 +731,7 @@ expiry_date = expiry_list.first[:expiry_date] # Use first expiry from above
731
731
 
732
732
  option_chain = DhanHQ::Models::OptionChain.fetch(
733
733
  underlying_scrip: "NIFTY",
734
- underlying_seg: "IDX_I",
734
+ underlying_seg: DhanHQ::Constants::ExchangeSegment::IDX_I,
735
735
  expiry: expiry_date
736
736
  )
737
737
 
@@ -835,22 +835,22 @@ super_order = DhanHQ::Models::SuperOrder.create(
835
835
  legs: [
836
836
  {
837
837
  leg_name: "ENTRY_LEG",
838
- transaction_type: "BUY",
839
- exchange_segment: "NSE_FNO",
840
- product_type: "MARGIN",
841
- order_type: "LIMIT",
842
- validity: "DAY",
838
+ transaction_type: DhanHQ::Constants::TransactionType::BUY,
839
+ exchange_segment: DhanHQ::Constants::ExchangeSegment::NSE_FNO,
840
+ product_type: DhanHQ::Constants::ProductType::MARGIN,
841
+ order_type: DhanHQ::Constants::OrderType::LIMIT,
842
+ validity: DhanHQ::Constants::Validity::DAY,
843
843
  security_id: "49081",
844
844
  quantity: 50,
845
845
  price: 18000.0
846
846
  },
847
847
  {
848
848
  leg_name: "EXIT_LEG",
849
- transaction_type: "SELL",
850
- exchange_segment: "NSE_FNO",
851
- product_type: "MARGIN",
852
- order_type: "LIMIT",
853
- validity: "DAY",
849
+ transaction_type: DhanHQ::Constants::TransactionType::SELL,
850
+ exchange_segment: DhanHQ::Constants::ExchangeSegment::NSE_FNO,
851
+ product_type: DhanHQ::Constants::ProductType::MARGIN,
852
+ order_type: DhanHQ::Constants::OrderType::LIMIT,
853
+ validity: DhanHQ::Constants::Validity::DAY,
854
854
  security_id: "49081",
855
855
  quantity: 50,
856
856
  price: 18100.0
@@ -891,10 +891,10 @@ puts "Total forever orders: #{forever_orders.size}"
891
891
  # Create a forever order (GTT)
892
892
  forever_order = DhanHQ::Models::ForeverOrder.create(
893
893
  dhan_client_id: "1000000003",
894
- transaction_type: "BUY",
895
- exchange_segment: "NSE_EQ",
896
- product_type: "MARGIN",
897
- order_type: "LIMIT",
894
+ transaction_type: DhanHQ::Constants::TransactionType::BUY,
895
+ exchange_segment: DhanHQ::Constants::ExchangeSegment::NSE_EQ,
896
+ product_type: DhanHQ::Constants::ProductType::MARGIN,
897
+ order_type: DhanHQ::Constants::OrderType::LIMIT,
898
898
  validity: "GTC",
899
899
  security_id: "11536",
900
900
  quantity: 1,
@@ -971,6 +971,8 @@ tc.status
971
971
 
972
972
  #### Kill Switch (model, backward compatible)
973
973
 
974
+ Uses query param per API doc: `POST /v2/killswitch?killSwitchStatus=ACTIVATE` (no body).
975
+
974
976
  ```ruby
975
977
  # Activate kill switch
976
978
  result = DhanHQ::Models::KillSwitch.update("ACTIVATE")
@@ -1010,10 +1012,10 @@ end
1010
1012
  # Calculate margin for an order
1011
1013
  margin = DhanHQ::Models::Margin.calculate(
1012
1014
  dhan_client_id: "1000000003",
1013
- transaction_type: "BUY",
1014
- exchange_segment: "NSE_EQ",
1015
- product_type: "MARGIN",
1016
- order_type: "LIMIT",
1015
+ transaction_type: DhanHQ::Constants::TransactionType::BUY,
1016
+ exchange_segment: DhanHQ::Constants::ExchangeSegment::NSE_EQ,
1017
+ product_type: DhanHQ::Constants::ProductType::MARGIN,
1018
+ order_type: DhanHQ::Constants::OrderType::LIMIT,
1017
1019
  security_id: "11536",
1018
1020
  quantity: 1,
1019
1021
  price: 3500.0
@@ -1054,11 +1056,11 @@ end
1054
1056
  # Test valid order
1055
1057
  valid_params = {
1056
1058
  dhan_client_id: "1000000003",
1057
- transaction_type: "BUY",
1058
- exchange_segment: "NSE_EQ",
1059
- product_type: "INTRADAY",
1060
- order_type: "LIMIT",
1061
- validity: "DAY",
1059
+ transaction_type: DhanHQ::Constants::TransactionType::BUY,
1060
+ exchange_segment: DhanHQ::Constants::ExchangeSegment::NSE_EQ,
1061
+ product_type: DhanHQ::Constants::ProductType::INTRADAY,
1062
+ order_type: DhanHQ::Constants::OrderType::LIMIT,
1063
+ validity: DhanHQ::Constants::Validity::DAY,
1062
1064
  security_id: "11536",
1063
1065
  quantity: 1,
1064
1066
  price: 3500.0
@@ -1074,8 +1076,8 @@ end
1074
1076
 
1075
1077
  # Test invalid order (missing required field)
1076
1078
  invalid_params = {
1077
- transaction_type: "BUY",
1078
- exchange_segment: "NSE_EQ"
1079
+ transaction_type: DhanHQ::Constants::TransactionType::BUY,
1080
+ exchange_segment: DhanHQ::Constants::ExchangeSegment::NSE_EQ
1079
1081
  # Missing required fields
1080
1082
  }
1081
1083
 
@@ -1133,10 +1135,10 @@ end
1133
1135
  # Test valid margin calculation
1134
1136
  valid_params = {
1135
1137
  dhan_client_id: "1000000003",
1136
- transaction_type: "BUY",
1137
- exchange_segment: "NSE_EQ",
1138
- product_type: "MARGIN",
1139
- order_type: "LIMIT",
1138
+ transaction_type: DhanHQ::Constants::TransactionType::BUY,
1139
+ exchange_segment: DhanHQ::Constants::ExchangeSegment::NSE_EQ,
1140
+ product_type: DhanHQ::Constants::ProductType::MARGIN,
1141
+ order_type: DhanHQ::Constants::OrderType::LIMIT,
1140
1142
  security_id: "11536",
1141
1143
  quantity: 1,
1142
1144
  price: 3500.0
@@ -1157,7 +1159,7 @@ end
1157
1159
  # Test valid option chain request
1158
1160
  valid_params = {
1159
1161
  underlying_scrip: "NIFTY",
1160
- underlying_seg: "IDX_I",
1162
+ underlying_seg: DhanHQ::Constants::ExchangeSegment::IDX_I,
1161
1163
  expiry: "2024-01-25"
1162
1164
  }
1163
1165
 
@@ -1183,7 +1185,7 @@ end
1183
1185
  # Test valid historical data request
1184
1186
  valid_params = {
1185
1187
  security_id: "11536",
1186
- exchange_segment: "NSE_EQ",
1188
+ exchange_segment: DhanHQ::Constants::ExchangeSegment::NSE_EQ,
1187
1189
  from_date: Date.today - 7,
1188
1190
  to_date: Date.today,
1189
1191
  interval: 5
@@ -1252,7 +1254,7 @@ end
1252
1254
  begin
1253
1255
  order = DhanHQ::Models::Order.place(
1254
1256
  transaction_type: "INVALID_TYPE",
1255
- exchange_segment: "NSE_EQ"
1257
+ exchange_segment: DhanHQ::Constants::ExchangeSegment::NSE_EQ
1256
1258
  )
1257
1259
  rescue DhanHQ::Error => e
1258
1260
  puts "Validation error caught: #{e.message}"
@@ -1327,10 +1329,10 @@ puts "1. Available Margin: ₹#{funds.available_margin}"
1327
1329
  # 2. Calculate margin
1328
1330
  margin = DhanHQ::Models::Margin.calculate(
1329
1331
  dhan_client_id: "1000000003",
1330
- transaction_type: "BUY",
1331
- exchange_segment: "NSE_EQ",
1332
- product_type: "MARGIN",
1333
- order_type: "LIMIT",
1332
+ transaction_type: DhanHQ::Constants::TransactionType::BUY,
1333
+ exchange_segment: DhanHQ::Constants::ExchangeSegment::NSE_EQ,
1334
+ product_type: DhanHQ::Constants::ProductType::MARGIN,
1335
+ order_type: DhanHQ::Constants::OrderType::LIMIT,
1334
1336
  security_id: "11536",
1335
1337
  quantity: 1,
1336
1338
  price: 3500.0
@@ -1340,11 +1342,11 @@ puts "2. Margin Required: ₹#{margin.margin_required}"
1340
1342
  # 3. Place order
1341
1343
  order = DhanHQ::Models::Order.place(
1342
1344
  dhan_client_id: "1000000003",
1343
- transaction_type: "BUY",
1344
- exchange_segment: "NSE_EQ",
1345
- product_type: "MARGIN",
1346
- order_type: "LIMIT",
1347
- validity: "DAY",
1345
+ transaction_type: DhanHQ::Constants::TransactionType::BUY,
1346
+ exchange_segment: DhanHQ::Constants::ExchangeSegment::NSE_EQ,
1347
+ product_type: DhanHQ::Constants::ProductType::MARGIN,
1348
+ order_type: DhanHQ::Constants::OrderType::LIMIT,
1349
+ validity: DhanHQ::Constants::Validity::DAY,
1348
1350
  security_id: "11536",
1349
1351
  quantity: 1,
1350
1352
  price: 3500.0
@@ -1363,7 +1365,7 @@ orders_client.start
1363
1365
  # 5. Modify order (if pending)
1364
1366
  sleep(2)
1365
1367
  order.refresh
1366
- if order.order_status == "PENDING"
1368
+ if order.order_status == DhanHQ::Constants::OrderStatus::PENDING
1367
1369
  if order.modify(price: 3501.0)
1368
1370
  puts "5. Order Modified"
1369
1371
  end
@@ -1390,7 +1392,7 @@ puts "=== Test Complete ==="
1390
1392
  # Get historical data and analyze
1391
1393
  historical_data = DhanHQ::Models::HistoricalData.daily(
1392
1394
  security_id: "11536",
1393
- exchange_segment: "NSE_EQ",
1395
+ exchange_segment: DhanHQ::Constants::ExchangeSegment::NSE_EQ,
1394
1396
  from_date: Date.today - 30,
1395
1397
  to_date: Date.today
1396
1398
  )
@@ -1419,13 +1421,13 @@ end
1419
1421
  # Get option chain
1420
1422
  expiry_list = DhanHQ::Models::OptionChain.fetch_expiry_list(
1421
1423
  underlying_scrip: "NIFTY",
1422
- underlying_seg: "IDX_I"
1424
+ underlying_seg: DhanHQ::Constants::ExchangeSegment::IDX_I
1423
1425
  )
1424
1426
 
1425
1427
  expiry = expiry_list.first[:expiry_date]
1426
1428
  option_chain = DhanHQ::Models::OptionChain.fetch(
1427
1429
  underlying_scrip: "NIFTY",
1428
- underlying_seg: "IDX_I",
1430
+ underlying_seg: DhanHQ::Constants::ExchangeSegment::IDX_I,
1429
1431
  expiry: expiry
1430
1432
  )
1431
1433
 
@@ -45,10 +45,10 @@ market_client = DhanHQ::WS.connect(mode: :ticker) do |tick|
45
45
  end
46
46
 
47
47
  # Subscribe to specific indices
48
- market_client.subscribe_one(segment: "IDX_I", security_id: "13") # NIFTY
49
- market_client.subscribe_one(segment: "IDX_I", security_id: "25") # BANKNIFTY
50
- market_client.subscribe_one(segment: "IDX_I", security_id: "29") # NIFTYIT
51
- market_client.subscribe_one(segment: "IDX_I", security_id: "51") # SENSEX
48
+ market_client.subscribe_one(segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "13") # NIFTY
49
+ market_client.subscribe_one(segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "25") # BANKNIFTY
50
+ market_client.subscribe_one(segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "29") # NIFTYIT
51
+ market_client.subscribe_one(segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "51") # SENSEX
52
52
 
53
53
  # Clean shutdown
54
54
  market_client.stop
@@ -136,20 +136,20 @@ end
136
136
  client = DhanHQ::WS.connect(mode: :ticker) { |tick| puts tick[:ltp] }
137
137
 
138
138
  # Subscribe to individual instruments
139
- client.subscribe_one(segment: "IDX_I", security_id: "13") # NIFTY
140
- client.subscribe_one(segment: "IDX_I", security_id: "25") # BANKNIFTY
141
- client.subscribe_one(segment: "NSE_EQ", security_id: "2885") # RELIANCE
139
+ client.subscribe_one(segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "13") # NIFTY
140
+ client.subscribe_one(segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "25") # BANKNIFTY
141
+ client.subscribe_one(segment: DhanHQ::Constants::ExchangeSegment::NSE_EQ, security_id: "2885") # RELIANCE
142
142
 
143
143
  # Subscribe to multiple instruments
144
144
  instruments = [
145
- { ExchangeSegment: "IDX_I", SecurityId: "13" },
146
- { ExchangeSegment: "IDX_I", SecurityId: "25" },
147
- { ExchangeSegment: "NSE_EQ", SecurityId: "2885" }
145
+ { ExchangeSegment: DhanHQ::Constants::ExchangeSegment::IDX_I, SecurityId: "13" },
146
+ { ExchangeSegment: DhanHQ::Constants::ExchangeSegment::IDX_I, SecurityId: "25" },
147
+ { ExchangeSegment: DhanHQ::Constants::ExchangeSegment::NSE_EQ, SecurityId: "2885" }
148
148
  ]
149
149
  client.subscribe_many(instruments)
150
150
 
151
151
  # Unsubscribe
152
- client.unsubscribe_one(segment: "IDX_I", security_id: "13")
152
+ client.unsubscribe_one(segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "13")
153
153
  ```
154
154
 
155
155
  #### Finding Correct Security IDs
@@ -297,8 +297,8 @@ end
297
297
 
298
298
  # Method 2: Direct specification (legacy)
299
299
  symbols_direct = [
300
- { symbol: "RELIANCE", exchange_segment: "NSE_EQ", security_id: "2885" },
301
- { symbol: "TCS", exchange_segment: "NSE_EQ", security_id: "11536" }
300
+ { symbol: "RELIANCE", exchange_segment: DhanHQ::Constants::ExchangeSegment::NSE_EQ, security_id: "2885" },
301
+ { symbol: "TCS", exchange_segment: DhanHQ::Constants::ExchangeSegment::NSE_EQ, security_id: "11536" }
302
302
  ]
303
303
 
304
304
  depth_client = DhanHQ::WS::MarketDepth.connect(symbols: symbols_direct) do |depth_data|
@@ -333,8 +333,8 @@ client.start
333
333
 
334
334
  # Subscribe to symbols
335
335
  symbols = [
336
- { symbol: "RELIANCE", exchange_segment: "NSE_EQ", security_id: "2885" },
337
- { symbol: "TCS", exchange_segment: "NSE_EQ", security_id: "11536" }
336
+ { symbol: "RELIANCE", exchange_segment: DhanHQ::Constants::ExchangeSegment::NSE_EQ, security_id: "2885" },
337
+ { symbol: "TCS", exchange_segment: DhanHQ::Constants::ExchangeSegment::NSE_EQ, security_id: "11536" }
338
338
  ]
339
339
  client.subscribe(symbols)
340
340
  ```
@@ -587,10 +587,10 @@ class MarketDataService
587
587
  end
588
588
 
589
589
  # Subscribe to indices
590
- @market_client.subscribe_one(segment: "IDX_I", security_id: "13") # NIFTY
591
- @market_client.subscribe_one(segment: "IDX_I", security_id: "25") # BANKNIFTY
592
- @market_client.subscribe_one(segment: "IDX_I", security_id: "29") # NIFTYIT
593
- @market_client.subscribe_one(segment: "IDX_I", security_id: "51") # SENSEX
590
+ @market_client.subscribe_one(segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "13") # NIFTY
591
+ @market_client.subscribe_one(segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "25") # BANKNIFTY
592
+ @market_client.subscribe_one(segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "29") # NIFTYIT
593
+ @market_client.subscribe_one(segment: DhanHQ::Constants::ExchangeSegment::IDX_I, security_id: "51") # SENSEX
594
594
  end
595
595
 
596
596
  def stop_market_feed
@@ -1,6 +1,6 @@
1
1
  # WebSocket Protocol Reference
2
2
 
3
- Low-level protocol details for the DhanHQ WebSocket market feed. For high-level usage, see the [WebSocket Integration Guide](websocket_integration.md).
3
+ Low-level protocol details for the DhanHQ WebSocket market feed. For high-level usage, see the [WebSocket Integration Guide](WEBSOCKET_INTEGRATION.md).
4
4
 
5
5
  ---
6
6
 
@@ -59,7 +59,7 @@ All ticks are delivered as a Ruby Hash with consistent keys:
59
59
  ```ruby
60
60
  {
61
61
  kind: :quote, # :ticker | :quote | :full | :oi | :prev_close | :misc
62
- segment: "NSE_FNO", # string enum
62
+ segment: DhanHQ::Constants::ExchangeSegment::NSE_FNO, # string enum
63
63
  security_id: "12345",
64
64
  ltp: 101.5,
65
65
  ts: 1723791300, # LTT epoch (sec) if present