DhanHQ 2.8.0 → 3.0.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 (79) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +7 -0
  3. data/CHANGELOG.md +19 -0
  4. data/README.md +16 -5
  5. data/docs/RAILS_WEBSOCKET_INTEGRATION.md +1 -1
  6. data/docs/STANDALONE_RUBY_WEBSOCKET_INTEGRATION.md +1 -1
  7. data/docs/TECHNICAL_ANALYSIS.md +1 -1
  8. data/exe/DhanHQ +1 -1
  9. data/lib/DhanHQ/agent/order_preview.rb +50 -0
  10. data/lib/DhanHQ/agent/policy.rb +51 -0
  11. data/lib/DhanHQ/agent/tool_registry.rb +250 -0
  12. data/lib/DhanHQ/agent.rb +12 -0
  13. data/lib/DhanHQ/ai/context_builder.rb +145 -0
  14. data/lib/DhanHQ/ai/prompt_helpers.rb +114 -0
  15. data/lib/DhanHQ/ai.rb +27 -0
  16. data/lib/DhanHQ/auth.rb +0 -1
  17. data/lib/DhanHQ/client.rb +1 -3
  18. data/lib/DhanHQ/constants.rb +2 -0
  19. data/lib/DhanHQ/contracts/iceberg_order_contract.rb +83 -0
  20. data/lib/DhanHQ/contracts/twap_order_contract.rb +106 -0
  21. data/lib/DhanHQ/core/auth_api.rb +0 -1
  22. data/lib/DhanHQ/errors.rb +4 -0
  23. data/lib/DhanHQ/events/base.rb +203 -0
  24. data/lib/DhanHQ/events/bus.rb +158 -0
  25. data/lib/DhanHQ/events.rb +40 -0
  26. data/lib/DhanHQ/indicators.rb +283 -0
  27. data/lib/DhanHQ/market_data/market_snapshot.rb +97 -0
  28. data/lib/DhanHQ/market_data/ohlc_series.rb +169 -0
  29. data/lib/DhanHQ/market_data/option_snapshot.rb +223 -0
  30. data/lib/DhanHQ/market_data.rb +25 -0
  31. data/lib/DhanHQ/mcp/server.rb +72 -0
  32. data/lib/DhanHQ/mcp.rb +10 -0
  33. data/lib/DhanHQ/models/funds.rb +12 -0
  34. data/lib/DhanHQ/models/holding.rb +42 -0
  35. data/lib/DhanHQ/models/iceberg_order.rb +139 -0
  36. data/lib/DhanHQ/models/instrument.rb +36 -0
  37. data/lib/DhanHQ/models/order.rb +95 -0
  38. data/lib/DhanHQ/models/position.rb +66 -0
  39. data/lib/DhanHQ/models/search_result.rb +12 -0
  40. data/lib/DhanHQ/models/trade.rb +13 -0
  41. data/lib/DhanHQ/models/twap_order.rb +136 -0
  42. data/lib/DhanHQ/option_analytics/black_scholes.rb +194 -0
  43. data/lib/DhanHQ/option_analytics/max_pain.rb +119 -0
  44. data/lib/DhanHQ/option_analytics.rb +36 -0
  45. data/lib/DhanHQ/resources/iceberg_orders.rb +61 -0
  46. data/lib/DhanHQ/resources/twap_orders.rb +61 -0
  47. data/lib/DhanHQ/risk/checks/asm_gsm.rb +17 -0
  48. data/lib/DhanHQ/risk/checks/market_hours.rb +37 -0
  49. data/lib/DhanHQ/risk/checks/options.rb +46 -0
  50. data/lib/DhanHQ/risk/checks/order_type.rb +20 -0
  51. data/lib/DhanHQ/risk/checks/product_support.rb +34 -0
  52. data/lib/DhanHQ/risk/checks/quantity.rb +32 -0
  53. data/lib/DhanHQ/risk/checks/trading_permission.rb +16 -0
  54. data/lib/DhanHQ/risk/pipeline.rb +65 -0
  55. data/lib/DhanHQ/risk.rb +250 -0
  56. data/lib/DhanHQ/skills/base.rb +132 -0
  57. data/lib/DhanHQ/skills/builtin/buy_atm_call.rb +87 -0
  58. data/lib/DhanHQ/skills/builtin/iron_condor.rb +93 -0
  59. data/lib/DhanHQ/skills/builtin/square_off_all.rb +45 -0
  60. data/lib/DhanHQ/skills/builtin/square_off_position.rb +48 -0
  61. data/lib/DhanHQ/skills/builtin/strangle.rb +93 -0
  62. data/lib/DhanHQ/skills/registry.rb +101 -0
  63. data/lib/DhanHQ/skills/workflow.rb +66 -0
  64. data/lib/DhanHQ/skills.rb +29 -0
  65. data/lib/DhanHQ/strategy/base.rb +189 -0
  66. data/lib/DhanHQ/strategy.rb +40 -0
  67. data/lib/DhanHQ/version.rb +1 -1
  68. data/lib/DhanHQ/ws/decoder.rb +57 -19
  69. data/lib/DhanHQ.rb +3 -0
  70. data/lib/dhan_hq/agent.rb +3 -0
  71. data/lib/dhan_hq/analysis.rb +9 -0
  72. data/lib/dhan_hq/mcp.rb +3 -0
  73. data/lib/dhan_hq/ta.rb +5 -0
  74. data/lib/dhan_hq.rb +27 -4
  75. data/lib/ta/technical_analysis.rb +3 -1
  76. data/skills/dhanhq-ruby/SKILL.md +74 -0
  77. data/skills/dhanhq-ruby/references/market_data.md +3 -0
  78. data/skills/dhanhq-ruby/references/orders.md +7 -0
  79. metadata +61 -20
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../DhanHQ/agent"
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dhan_hq"
4
+
5
+ require_relative "../dhanhq/contracts/options_buying_advisor_contract"
6
+ require_relative "../dhanhq/analysis/helpers/bias_aggregator"
7
+ require_relative "../dhanhq/analysis/helpers/moneyness_helper"
8
+ require_relative "../dhanhq/analysis/multi_timeframe_analyzer"
9
+ require_relative "../dhanhq/analysis/options_buying_advisor"
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../DhanHQ/mcp"
data/lib/dhan_hq/ta.rb ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dhan_hq"
4
+
5
+ require_relative "../ta"
data/lib/dhan_hq.rb CHANGED
@@ -34,16 +34,39 @@ module DhanHQ
34
34
  "ws" => "WS"
35
35
  )
36
36
  LOADER.push_dir(File.join(__dir__, "DhanHQ"), namespace: self)
37
- LOADER.push_dir(File.join(__dir__, "dhanhq"), namespace: self)
38
37
  LOADER.collapse(File.join(__dir__, "DhanHQ", "core"))
39
38
  LOADER.collapse(File.join(__dir__, "DhanHQ", "helpers"))
40
- LOADER.collapse(File.join(__dir__, "dhanhq", "analysis", "helpers"))
41
39
  LOADER.ignore(
42
40
  File.join(__dir__, "DhanHQ", "errors.rb"),
43
- File.join(__dir__, "DhanHQ", "version.rb")
41
+ File.join(__dir__, "DhanHQ", "version.rb"),
42
+ File.join(__dir__, "DhanHQ", "risk.rb")
44
43
  )
45
44
  LOADER.setup
46
45
 
46
+ # Eager-load risk utilities (PositionSizer, SLCalculator, TrailManager)
47
+ # and the pre-execution risk pipeline so they are available immediately.
48
+ require_relative "DhanHQ/risk"
49
+ require_relative "DhanHQ/risk/checks/trading_permission"
50
+ require_relative "DhanHQ/risk/checks/asm_gsm"
51
+ require_relative "DhanHQ/risk/checks/product_support"
52
+ require_relative "DhanHQ/risk/checks/order_type"
53
+ require_relative "DhanHQ/risk/checks/quantity"
54
+ require_relative "DhanHQ/risk/checks/market_hours"
55
+ require_relative "DhanHQ/risk/checks/options"
56
+ require_relative "DhanHQ/risk/pipeline"
57
+
58
+ # Skills layer: multi-step trading workflows
59
+ require_relative "DhanHQ/skills"
60
+ require_relative "DhanHQ/skills/base"
61
+ require_relative "DhanHQ/skills/registry"
62
+ require_relative "DhanHQ/skills/workflow"
63
+ require_relative "DhanHQ/skills/builtin/buy_atm_call"
64
+ require_relative "DhanHQ/skills/builtin/square_off_all"
65
+ require_relative "DhanHQ/skills/builtin/square_off_position"
66
+ require_relative "DhanHQ/skills/builtin/iron_condor"
67
+ require_relative "DhanHQ/skills/builtin/strangle"
68
+ DhanHQ::Skills::Registry.load_builtins
69
+
47
70
  class Error < StandardError; end
48
71
 
49
72
  class << self
@@ -133,7 +156,7 @@ module DhanHQ
133
156
 
134
157
  url = "#{base_url.to_s.chomp("/")}/auth/dhan/token"
135
158
  conn = ::Faraday.new(url: url) do |c|
136
- c.response :json, content_type: /\bjson$/
159
+ c.request :url_encoded
137
160
  c.adapter ::Faraday.default_adapter
138
161
  end
139
162
 
@@ -125,7 +125,9 @@ module TA
125
125
  def normalize_from_date(from_date, to_date, days_back)
126
126
  if (from_date.nil? || from_date.to_s.strip.empty?) && days_back&.to_i&.positive?
127
127
  to_d = Date.parse(to_date)
128
- n_back = [days_back.to_i - 1, 0].max
128
+ # Dhan historical API to_date is non-inclusive. To get N trading days,
129
+ # we must go back N trading days from the non-inclusive to_date.
130
+ n_back = days_back.to_i
129
131
  return MarketCalendar.trading_days_ago(to_d, n_back).strftime("%Y-%m-%d")
130
132
  end
131
133
  if from_date && !from_date.to_s.strip.empty?
@@ -0,0 +1,74 @@
1
+ # DhanHQ Ruby SDK Skill
2
+
3
+ Use this skill when an agent needs to write, review, or operate Ruby code using the `DhanHQ` gem.
4
+
5
+ ## Safety rules
6
+
7
+ - Prefer read-only tools and SDK calls unless the user explicitly asks to trade.
8
+ - Resolve instruments before trading with `DhanHQ::Models::Instrument.search` and use the returned `security_id` plus `exchange_segment`.
9
+ - Preview every order with `DhanHQ::Agent::OrderPreview` before any live order placement.
10
+ - Never place, modify, or cancel orders unless both `DHANHQ_MCP_ENABLE_WRITES=true` and `LIVE_TRADING=true` are set and the user has clearly confirmed the action.
11
+ - Include a `correlation_id` for every agent-originated order.
12
+ - Do not ask for or print access tokens.
13
+
14
+ ## Setup
15
+
16
+ ```ruby
17
+ require "dhan_hq"
18
+ require "dhan_hq/agent"
19
+
20
+ DhanHQ.configure_with_env
21
+ ```
22
+
23
+ Required environment variables:
24
+
25
+ - `DHAN_CLIENT_ID`
26
+ - `DHAN_ACCESS_TOKEN`
27
+
28
+ Optional agent variables:
29
+
30
+ - `DHANHQ_AGENT_SCOPES`, comma-separated scopes such as `portfolio:read,market:read,orders:read`
31
+ - `DHANHQ_MCP_ENABLE_WRITES=true` for agent write tools
32
+ - `LIVE_TRADING=true` for any live trading write
33
+
34
+ ## Common calls
35
+
36
+ ```ruby
37
+ DhanHQ::Models::Profile.fetch
38
+ DhanHQ::Models::Funds.fetch
39
+ DhanHQ::Models::Holding.all
40
+ DhanHQ::Models::Position.all
41
+ DhanHQ::Models::Order.all
42
+ DhanHQ::Models::Trade.today
43
+ DhanHQ::Models::Instrument.search("RELIANCE", segments: ["NSE_EQ"], limit: 5)
44
+ DhanHQ::Models::MarketFeed.ltp("NSE_EQ" => ["2885"])
45
+ ```
46
+
47
+ ## Order preview
48
+
49
+ ```ruby
50
+ preview = DhanHQ::Agent::OrderPreview.new(
51
+ transaction_type: "BUY",
52
+ exchange_segment: "NSE_EQ",
53
+ product_type: "INTRADAY",
54
+ order_type: "MARKET",
55
+ validity: "DAY",
56
+ security_id: "2885",
57
+ quantity: 1,
58
+ correlation_id: "agent-20260702-001"
59
+ )
60
+
61
+ preview.to_h
62
+ ```
63
+
64
+ ## MCP server
65
+
66
+ The gem includes a stdio MCP executable:
67
+
68
+ ```bash
69
+ dhanhq-mcp
70
+ ```
71
+
72
+ Start with read-only scopes. Add write scopes only for explicitly confirmed trading sessions.
73
+
74
+ See the references directory for focused workflows.
@@ -0,0 +1,3 @@
1
+ # Market data with agents
2
+
3
+ Use `DhanHQ::Models::Instrument.search` to resolve a query to Dhan security IDs, then call `DhanHQ::Models::MarketFeed.ltp`, `.ohlc`, or `.quote` with an exchange-segment keyed payload.
@@ -0,0 +1,7 @@
1
+ # Orders with agents
2
+
3
+ 1. Search or otherwise verify the instrument.
4
+ 2. Build order params using Dhan constants and API docs.
5
+ 3. Run `DhanHQ::Agent::OrderPreview.new(params).to_h`.
6
+ 4. Ask the user to confirm the preview.
7
+ 5. Place only if `DHANHQ_MCP_ENABLE_WRITES=true`, `LIVE_TRADING=true`, and `orders:write` scope are present.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: DhanHQ
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.8.0
4
+ version: 3.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shubham Taywade
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-03-21 00:00:00.000000000 Z
11
+ date: 2026-07-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -112,30 +112,16 @@ dependencies:
112
112
  name: faraday
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - ">="
115
+ - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '0'
117
+ version: '2.14'
118
118
  type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - ">="
123
- - !ruby/object:Gem::Version
124
- version: '0'
125
- - !ruby/object:Gem::Dependency
126
- name: faraday_middleware
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - ">="
122
+ - - "~>"
130
123
  - !ruby/object:Gem::Version
131
- version: '0'
132
- type: :runtime
133
- prerelease: false
134
- version_requirements: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - ">="
137
- - !ruby/object:Gem::Version
138
- version: '0'
124
+ version: '2.14'
139
125
  - !ruby/object:Gem::Dependency
140
126
  name: faye-websocket
141
127
  requirement: !ruby/object:Gem::Requirement
@@ -230,6 +216,14 @@ files:
230
216
  - docs/WEBSOCKET_PROTOCOL.md
231
217
  - docs/architecture-overview.svg
232
218
  - exe/DhanHQ
219
+ - lib/DhanHQ.rb
220
+ - lib/DhanHQ/agent.rb
221
+ - lib/DhanHQ/agent/order_preview.rb
222
+ - lib/DhanHQ/agent/policy.rb
223
+ - lib/DhanHQ/agent/tool_registry.rb
224
+ - lib/DhanHQ/ai.rb
225
+ - lib/DhanHQ/ai/context_builder.rb
226
+ - lib/DhanHQ/ai/prompt_helpers.rb
233
227
  - lib/DhanHQ/auth.rb
234
228
  - lib/DhanHQ/auth/token_generator.rb
235
229
  - lib/DhanHQ/auth/token_manager.rb
@@ -244,6 +238,7 @@ files:
244
238
  - lib/DhanHQ/contracts/expired_options_data_contract.rb
245
239
  - lib/DhanHQ/contracts/forever_order_contract.rb
246
240
  - lib/DhanHQ/contracts/historical_data_contract.rb
241
+ - lib/DhanHQ/contracts/iceberg_order_contract.rb
247
242
  - lib/DhanHQ/contracts/instrument_list_contract.rb
248
243
  - lib/DhanHQ/contracts/intraday_historical_data_contract.rb
249
244
  - lib/DhanHQ/contracts/margin_calculator_contract.rb
@@ -259,6 +254,7 @@ files:
259
254
  - lib/DhanHQ/contracts/trade_by_order_id_contract.rb
260
255
  - lib/DhanHQ/contracts/trade_contract.rb
261
256
  - lib/DhanHQ/contracts/trade_history_contract.rb
257
+ - lib/DhanHQ/contracts/twap_order_contract.rb
262
258
  - lib/DhanHQ/contracts/user_ip_contract.rb
263
259
  - lib/DhanHQ/core/auth_api.rb
264
260
  - lib/DhanHQ/core/base_api.rb
@@ -267,13 +263,23 @@ files:
267
263
  - lib/DhanHQ/core/error_handler.rb
268
264
  - lib/DhanHQ/error_object.rb
269
265
  - lib/DhanHQ/errors.rb
266
+ - lib/DhanHQ/events.rb
267
+ - lib/DhanHQ/events/base.rb
268
+ - lib/DhanHQ/events/bus.rb
270
269
  - lib/DhanHQ/helpers/api_helper.rb
271
270
  - lib/DhanHQ/helpers/attribute_helper.rb
272
271
  - lib/DhanHQ/helpers/model_helper.rb
273
272
  - lib/DhanHQ/helpers/request_helper.rb
274
273
  - lib/DhanHQ/helpers/response_helper.rb
275
274
  - lib/DhanHQ/helpers/validation_helper.rb
275
+ - lib/DhanHQ/indicators.rb
276
276
  - lib/DhanHQ/json_loader.rb
277
+ - lib/DhanHQ/market_data.rb
278
+ - lib/DhanHQ/market_data/market_snapshot.rb
279
+ - lib/DhanHQ/market_data/ohlc_series.rb
280
+ - lib/DhanHQ/market_data/option_snapshot.rb
281
+ - lib/DhanHQ/mcp.rb
282
+ - lib/DhanHQ/mcp/server.rb
277
283
  - lib/DhanHQ/models/alert_order.rb
278
284
  - lib/DhanHQ/models/concerns/api_response_handler.rb
279
285
  - lib/DhanHQ/models/edis.rb
@@ -282,6 +288,7 @@ files:
282
288
  - lib/DhanHQ/models/funds.rb
283
289
  - lib/DhanHQ/models/historical_data.rb
284
290
  - lib/DhanHQ/models/holding.rb
291
+ - lib/DhanHQ/models/iceberg_order.rb
285
292
  - lib/DhanHQ/models/instrument.rb
286
293
  - lib/DhanHQ/models/instrument_helpers.rb
287
294
  - lib/DhanHQ/models/kill_switch.rb
@@ -295,9 +302,14 @@ files:
295
302
  - lib/DhanHQ/models/position.rb
296
303
  - lib/DhanHQ/models/postback.rb
297
304
  - lib/DhanHQ/models/profile.rb
305
+ - lib/DhanHQ/models/search_result.rb
298
306
  - lib/DhanHQ/models/super_order.rb
299
307
  - lib/DhanHQ/models/token_response.rb
300
308
  - lib/DhanHQ/models/trade.rb
309
+ - lib/DhanHQ/models/twap_order.rb
310
+ - lib/DhanHQ/option_analytics.rb
311
+ - lib/DhanHQ/option_analytics/black_scholes.rb
312
+ - lib/DhanHQ/option_analytics/max_pain.rb
301
313
  - lib/DhanHQ/rate_limiter.rb
302
314
  - lib/DhanHQ/requests/optionchain/nifty.json
303
315
  - lib/DhanHQ/requests/optionchain/nifty_expiries.json
@@ -309,6 +321,7 @@ files:
309
321
  - lib/DhanHQ/resources/funds.rb
310
322
  - lib/DhanHQ/resources/historical_data.rb
311
323
  - lib/DhanHQ/resources/holdings.rb
324
+ - lib/DhanHQ/resources/iceberg_orders.rb
312
325
  - lib/DhanHQ/resources/instruments.rb
313
326
  - lib/DhanHQ/resources/ip_setup.rb
314
327
  - lib/DhanHQ/resources/kill_switch.rb
@@ -323,6 +336,27 @@ files:
323
336
  - lib/DhanHQ/resources/super_orders.rb
324
337
  - lib/DhanHQ/resources/trader_control.rb
325
338
  - lib/DhanHQ/resources/trades.rb
339
+ - lib/DhanHQ/resources/twap_orders.rb
340
+ - lib/DhanHQ/risk.rb
341
+ - lib/DhanHQ/risk/checks/asm_gsm.rb
342
+ - lib/DhanHQ/risk/checks/market_hours.rb
343
+ - lib/DhanHQ/risk/checks/options.rb
344
+ - lib/DhanHQ/risk/checks/order_type.rb
345
+ - lib/DhanHQ/risk/checks/product_support.rb
346
+ - lib/DhanHQ/risk/checks/quantity.rb
347
+ - lib/DhanHQ/risk/checks/trading_permission.rb
348
+ - lib/DhanHQ/risk/pipeline.rb
349
+ - lib/DhanHQ/skills.rb
350
+ - lib/DhanHQ/skills/base.rb
351
+ - lib/DhanHQ/skills/builtin/buy_atm_call.rb
352
+ - lib/DhanHQ/skills/builtin/iron_condor.rb
353
+ - lib/DhanHQ/skills/builtin/square_off_all.rb
354
+ - lib/DhanHQ/skills/builtin/square_off_position.rb
355
+ - lib/DhanHQ/skills/builtin/strangle.rb
356
+ - lib/DhanHQ/skills/registry.rb
357
+ - lib/DhanHQ/skills/workflow.rb
358
+ - lib/DhanHQ/strategy.rb
359
+ - lib/DhanHQ/strategy/base.rb
326
360
  - lib/DhanHQ/utils/network_inspector.rb
327
361
  - lib/DhanHQ/version.rb
328
362
  - lib/DhanHQ/ws.rb
@@ -354,6 +388,10 @@ files:
354
388
  - lib/DhanHQ/ws/sub_state.rb
355
389
  - lib/DhanHQ/ws/websocket_packet_parser.rb
356
390
  - lib/dhan_hq.rb
391
+ - lib/dhan_hq/agent.rb
392
+ - lib/dhan_hq/analysis.rb
393
+ - lib/dhan_hq/mcp.rb
394
+ - lib/dhan_hq/ta.rb
357
395
  - lib/dhanhq/analysis/helpers/bias_aggregator.rb
358
396
  - lib/dhanhq/analysis/helpers/moneyness_helper.rb
359
397
  - lib/dhanhq/analysis/multi_timeframe_analyzer.rb
@@ -367,6 +405,9 @@ files:
367
405
  - lib/ta/market_calendar.rb
368
406
  - lib/ta/technical_analysis.rb
369
407
  - sig/DhanHQ.rbs
408
+ - skills/dhanhq-ruby/SKILL.md
409
+ - skills/dhanhq-ruby/references/market_data.md
410
+ - skills/dhanhq-ruby/references/orders.md
370
411
  - watchlist.csv
371
412
  homepage: https://github.com/shubhamtaywade82/dhanhq-client
372
413
  licenses: