DhanHQ 2.1.8 → 2.1.10
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 +50 -0
- data/lib/DhanHQ/contracts/expired_options_data_contract.rb +6 -6
- data/lib/DhanHQ/core/base_model.rb +9 -1
- data/lib/DhanHQ/models/edis.rb +150 -14
- data/lib/DhanHQ/models/expired_options_data.rb +307 -82
- data/lib/DhanHQ/models/forever_order.rb +261 -22
- data/lib/DhanHQ/models/funds.rb +76 -10
- data/lib/DhanHQ/models/historical_data.rb +148 -31
- data/lib/DhanHQ/models/holding.rb +82 -6
- data/lib/DhanHQ/models/kill_switch.rb +113 -11
- data/lib/DhanHQ/models/ledger_entry.rb +101 -13
- data/lib/DhanHQ/models/margin.rb +133 -8
- data/lib/DhanHQ/models/market_feed.rb +181 -17
- data/lib/DhanHQ/models/option_chain.rb +184 -12
- data/lib/DhanHQ/models/order.rb +399 -34
- data/lib/DhanHQ/models/position.rb +161 -10
- data/lib/DhanHQ/models/profile.rb +103 -7
- data/lib/DhanHQ/models/super_order.rb +275 -15
- data/lib/DhanHQ/models/trade.rb +279 -26
- data/lib/DhanHQ/resources/expired_options_data.rb +1 -1
- data/lib/DhanHQ/version.rb +1 -1
- data/lib/DhanHQ/ws/orders/client.rb +2 -1
- data/lib/DhanHQ/ws/orders.rb +2 -1
- metadata +1 -1
|
@@ -3,8 +3,45 @@
|
|
|
3
3
|
module DhanHQ
|
|
4
4
|
module Models
|
|
5
5
|
##
|
|
6
|
-
#
|
|
7
|
-
#
|
|
6
|
+
# Model for fetching expired options contract data on a rolling basis.
|
|
7
|
+
#
|
|
8
|
+
# This API provides pre-processed expired options data for up to the last 5 years.
|
|
9
|
+
# Data is available on a minute-level basis, organized by strike price relative to spot
|
|
10
|
+
# (e.g., ATM, ATM+1, ATM-1, etc.). You can fetch up to 31 days of data in a single API call.
|
|
11
|
+
#
|
|
12
|
+
# Available data includes:
|
|
13
|
+
# - OHLC (Open, High, Low, Close) prices
|
|
14
|
+
# - Volume and Open Interest
|
|
15
|
+
# - Implied Volatility (IV)
|
|
16
|
+
# - Strike prices
|
|
17
|
+
# - Spot prices
|
|
18
|
+
# - Timestamps
|
|
19
|
+
#
|
|
20
|
+
# Strike ranges:
|
|
21
|
+
# - Index Options (near expiry): Up to ATM+10 / ATM-10
|
|
22
|
+
# - All other contracts: Up to ATM+3 / ATM-3
|
|
23
|
+
#
|
|
24
|
+
# @example Fetch expired options data for NIFTY
|
|
25
|
+
# data = DhanHQ::Models::ExpiredOptionsData.fetch(
|
|
26
|
+
# exchange_segment: "NSE_FNO",
|
|
27
|
+
# interval: "1",
|
|
28
|
+
# security_id: 13,
|
|
29
|
+
# instrument: "OPTIDX",
|
|
30
|
+
# expiry_flag: "MONTH",
|
|
31
|
+
# expiry_code: 1,
|
|
32
|
+
# strike: "ATM",
|
|
33
|
+
# drv_option_type: "CALL",
|
|
34
|
+
# required_data: ["open", "high", "low", "close", "volume"],
|
|
35
|
+
# from_date: "2021-08-01",
|
|
36
|
+
# to_date: "2021-09-01"
|
|
37
|
+
# )
|
|
38
|
+
# ohlc = data.ohlc_data
|
|
39
|
+
# volumes = data.volume_data
|
|
40
|
+
#
|
|
41
|
+
# @example Access call option data
|
|
42
|
+
# call_data = data.call_data
|
|
43
|
+
# put_data = data.put_data
|
|
44
|
+
#
|
|
8
45
|
# rubocop:disable Metrics/ClassLength
|
|
9
46
|
class ExpiredOptionsData < BaseModel
|
|
10
47
|
# All expired options data attributes
|
|
@@ -14,27 +51,74 @@ module DhanHQ
|
|
|
14
51
|
|
|
15
52
|
class << self
|
|
16
53
|
##
|
|
17
|
-
#
|
|
18
|
-
# POST /charts/rollingoption
|
|
54
|
+
# Fetches expired options data for rolling contracts on a minute-level basis.
|
|
19
55
|
#
|
|
20
|
-
#
|
|
21
|
-
#
|
|
22
|
-
#
|
|
23
|
-
# @
|
|
24
|
-
#
|
|
25
|
-
#
|
|
26
|
-
#
|
|
27
|
-
#
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
#
|
|
32
|
-
#
|
|
56
|
+
# Data is organized by strike price relative to spot and can be fetched for up to
|
|
57
|
+
# 31 days in a single request. Historical data is available for up to the last 5 years.
|
|
58
|
+
#
|
|
59
|
+
# @param params [Hash{Symbol => String, Integer, Array<String>}] Request parameters
|
|
60
|
+
# @option params [String] :exchange_segment (required) Exchange and segment identifier.
|
|
61
|
+
# Valid values: "NSE_FNO", "BSE_FNO", "NSE_EQ", "BSE_EQ"
|
|
62
|
+
# @option params [String] :interval (required) Minute intervals for the timeframe.
|
|
63
|
+
# Valid values: "1", "5", "15", "25", "60"
|
|
64
|
+
# @option params [Integer] :security_id (required) Underlying exchange standard ID for each scrip
|
|
65
|
+
# @option params [String] :instrument (required) Instrument type of the scrip.
|
|
66
|
+
# Valid values: "OPTIDX" (Index Options), "OPTSTK" (Stock Options)
|
|
67
|
+
# @option params [String] :expiry_flag (required) Expiry interval of the instrument.
|
|
68
|
+
# Valid values: "WEEK", "MONTH"
|
|
69
|
+
# @option params [Integer] :expiry_code (required) Expiry code for the instrument
|
|
70
|
+
# @option params [String] :strike (required) Strike price specification.
|
|
71
|
+
# Format: "ATM" for At The Money, "ATM+X" or "ATM-X" for offset strikes.
|
|
72
|
+
# For Index Options (near expiry): Up to ATM+10 / ATM-10
|
|
73
|
+
# For all other contracts: Up to ATM+3 / ATM-3
|
|
74
|
+
# @option params [String] :drv_option_type (required) Option type.
|
|
75
|
+
# Valid values: "CALL", "PUT"
|
|
76
|
+
# @option params [Array<String>] :required_data (required) Array of required data fields.
|
|
77
|
+
# Valid values: "open", "high", "low", "close", "iv", "volume", "strike", "oi", "spot"
|
|
78
|
+
# @option params [String] :from_date (required) Start date of the desired range in YYYY-MM-DD format.
|
|
79
|
+
# Cannot be more than 5 years ago. Same-day ranges are allowed.
|
|
80
|
+
# @option params [String] :to_date (required) End date of the desired range (non-inclusive) in YYYY-MM-DD format.
|
|
81
|
+
# Date range cannot exceed 31 days from from_date (to_date is non-inclusive). Same-day `from_date`/`to_date` is valid.
|
|
82
|
+
#
|
|
83
|
+
# @return [ExpiredOptionsData] Expired options data object with fetched data
|
|
84
|
+
#
|
|
85
|
+
# @example Fetch NIFTY index options data
|
|
86
|
+
# data = DhanHQ::Models::ExpiredOptionsData.fetch(
|
|
87
|
+
# exchange_segment: "NSE_FNO",
|
|
88
|
+
# interval: "1",
|
|
89
|
+
# security_id: 13,
|
|
90
|
+
# instrument: "OPTIDX",
|
|
91
|
+
# expiry_flag: "MONTH",
|
|
92
|
+
# expiry_code: 1,
|
|
93
|
+
# strike: "ATM",
|
|
94
|
+
# drv_option_type: "CALL",
|
|
95
|
+
# required_data: ["open", "high", "low", "close", "volume", "iv", "oi", "spot"],
|
|
96
|
+
# from_date: "2021-08-01",
|
|
97
|
+
# to_date: "2021-09-01"
|
|
98
|
+
# )
|
|
99
|
+
#
|
|
100
|
+
# @example Fetch stock options data for ATM+2 strike
|
|
101
|
+
# data = DhanHQ::Models::ExpiredOptionsData.fetch(
|
|
102
|
+
# exchange_segment: "NSE_FNO",
|
|
103
|
+
# interval: "15",
|
|
104
|
+
# security_id: 11536,
|
|
105
|
+
# instrument: "OPTSTK",
|
|
106
|
+
# expiry_flag: "WEEK",
|
|
107
|
+
# expiry_code: 0,
|
|
108
|
+
# strike: "ATM+2",
|
|
109
|
+
# drv_option_type: "PUT",
|
|
110
|
+
# required_data: ["open", "high", "low", "close", "volume"],
|
|
111
|
+
# from_date: "2024-01-01",
|
|
112
|
+
# to_date: "2024-01-31"
|
|
113
|
+
# )
|
|
114
|
+
#
|
|
115
|
+
# @raise [DhanHQ::ValidationError] If validation fails for any parameter
|
|
33
116
|
def fetch(params)
|
|
34
|
-
|
|
117
|
+
normalized = normalize_params(params)
|
|
118
|
+
validate_params(normalized)
|
|
35
119
|
|
|
36
|
-
response = expired_options_resource.fetch(
|
|
37
|
-
new(response.merge(
|
|
120
|
+
response = expired_options_resource.fetch(normalized)
|
|
121
|
+
new(response.merge(normalized), skip_validation: true)
|
|
38
122
|
end
|
|
39
123
|
|
|
40
124
|
private
|
|
@@ -51,6 +135,50 @@ module DhanHQ
|
|
|
51
135
|
|
|
52
136
|
raise DhanHQ::ValidationError, "Invalid parameters: #{validation_result.errors.to_h}"
|
|
53
137
|
end
|
|
138
|
+
|
|
139
|
+
# Best-effort normalization: coerce convertible values into expected shapes.
|
|
140
|
+
# Only values that are not convertible will fail validation.
|
|
141
|
+
def normalize_params(params)
|
|
142
|
+
normalized = params.dup
|
|
143
|
+
|
|
144
|
+
# interval: accept Integer or String, normalize to String
|
|
145
|
+
normalized[:interval] = normalized[:interval].to_s if normalized.key?(:interval)
|
|
146
|
+
|
|
147
|
+
# security_id, expiry_code: accept String or Integer, normalize to Integer if possible
|
|
148
|
+
if normalized.key?(:security_id)
|
|
149
|
+
original = normalized[:security_id]
|
|
150
|
+
converted = Integer(original, exception: false)
|
|
151
|
+
normalized[:security_id] = converted || original
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
if normalized.key?(:expiry_code)
|
|
155
|
+
original = normalized[:expiry_code]
|
|
156
|
+
converted = Integer(original, exception: false)
|
|
157
|
+
normalized[:expiry_code] = converted || original
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# Uppercase enums where appropriate
|
|
161
|
+
%i[exchange_segment instrument expiry_flag drv_option_type].each do |k|
|
|
162
|
+
next unless normalized.key?(k)
|
|
163
|
+
|
|
164
|
+
v = normalized[k]
|
|
165
|
+
normalized[k] = v.to_s.upcase
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# required_data: array of strings, downcased unique
|
|
169
|
+
if normalized.key?(:required_data)
|
|
170
|
+
normalized[:required_data] = Array(normalized[:required_data]).map { |x| x.to_s.downcase }.uniq
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# strike: ensure string
|
|
174
|
+
normalized[:strike] = normalized[:strike].to_s.upcase if normalized.key?(:strike)
|
|
175
|
+
|
|
176
|
+
# dates: ensure string (contract validates format)
|
|
177
|
+
normalized[:from_date] = normalized[:from_date].to_s if normalized.key?(:from_date)
|
|
178
|
+
normalized[:to_date] = normalized[:to_date].to_s if normalized.key?(:to_date)
|
|
179
|
+
|
|
180
|
+
normalized
|
|
181
|
+
end
|
|
54
182
|
end
|
|
55
183
|
|
|
56
184
|
##
|
|
@@ -60,8 +188,21 @@ module DhanHQ
|
|
|
60
188
|
end
|
|
61
189
|
|
|
62
190
|
##
|
|
63
|
-
#
|
|
64
|
-
#
|
|
191
|
+
# Gets call option data from the response.
|
|
192
|
+
#
|
|
193
|
+
# @return [Hash{Symbol => Array<Float, Integer>}, nil] Call option data hash containing arrays
|
|
194
|
+
# of OHLC, volume, IV, OI, strike, spot, and timestamps. Returns nil if call option data
|
|
195
|
+
# is not available in the response. Keys are normalized to snake_case:
|
|
196
|
+
# - **:open** [Array<Float>] Open prices
|
|
197
|
+
# - **:high** [Array<Float>] High prices
|
|
198
|
+
# - **:low** [Array<Float>] Low prices
|
|
199
|
+
# - **:close** [Array<Float>] Close prices
|
|
200
|
+
# - **:volume** [Array<Integer>] Volume traded
|
|
201
|
+
# - **:iv** [Array<Float>] Implied volatility values
|
|
202
|
+
# - **:oi** [Array<Float>] Open interest values
|
|
203
|
+
# - **:strike** [Array<Float>] Strike prices
|
|
204
|
+
# - **:spot** [Array<Float>] Spot prices
|
|
205
|
+
# - **:timestamp** [Array<Integer>] Epoch timestamps
|
|
65
206
|
def call_data
|
|
66
207
|
return nil unless data.is_a?(Hash)
|
|
67
208
|
|
|
@@ -69,8 +210,21 @@ module DhanHQ
|
|
|
69
210
|
end
|
|
70
211
|
|
|
71
212
|
##
|
|
72
|
-
#
|
|
73
|
-
#
|
|
213
|
+
# Gets put option data from the response.
|
|
214
|
+
#
|
|
215
|
+
# @return [Hash{Symbol => Array<Float, Integer>}, nil] Put option data hash containing arrays
|
|
216
|
+
# of OHLC, volume, IV, OI, strike, spot, and timestamps. Returns nil if put option data
|
|
217
|
+
# is not available in the response. Keys are normalized to snake_case:
|
|
218
|
+
# - **:open** [Array<Float>] Open prices
|
|
219
|
+
# - **:high** [Array<Float>] High prices
|
|
220
|
+
# - **:low** [Array<Float>] Low prices
|
|
221
|
+
# - **:close** [Array<Float>] Close prices
|
|
222
|
+
# - **:volume** [Array<Integer>] Volume traded
|
|
223
|
+
# - **:iv** [Array<Float>] Implied volatility values
|
|
224
|
+
# - **:oi** [Array<Float>] Open interest values
|
|
225
|
+
# - **:strike** [Array<Float>] Strike prices
|
|
226
|
+
# - **:spot** [Array<Float>] Spot prices
|
|
227
|
+
# - **:timestamp** [Array<Integer>] Epoch timestamps
|
|
74
228
|
def put_data
|
|
75
229
|
return nil unless data.is_a?(Hash)
|
|
76
230
|
|
|
@@ -78,9 +232,11 @@ module DhanHQ
|
|
|
78
232
|
end
|
|
79
233
|
|
|
80
234
|
##
|
|
81
|
-
#
|
|
82
|
-
#
|
|
83
|
-
# @
|
|
235
|
+
# Gets data for the specified option type.
|
|
236
|
+
#
|
|
237
|
+
# @param option_type [String] Option type to retrieve. Valid values: "CALL", "PUT"
|
|
238
|
+
# @return [Hash{Symbol => Array<Float, Integer>}, nil] Option data hash or nil if not available.
|
|
239
|
+
# See {#call_data} or {#put_data} for structure details.
|
|
84
240
|
def data_for_type(option_type)
|
|
85
241
|
case option_type.upcase
|
|
86
242
|
when "CALL"
|
|
@@ -91,9 +247,16 @@ module DhanHQ
|
|
|
91
247
|
end
|
|
92
248
|
|
|
93
249
|
##
|
|
94
|
-
#
|
|
95
|
-
#
|
|
96
|
-
# @
|
|
250
|
+
# Gets OHLC (Open, High, Low, Close) data for the specified option type.
|
|
251
|
+
#
|
|
252
|
+
# @param option_type [String, nil] Option type to retrieve ("CALL" or "PUT").
|
|
253
|
+
# If nil, uses the {#drv_option_type} from the request.
|
|
254
|
+
# @return [Hash{Symbol => Array<Float>}] OHLC data hash with:
|
|
255
|
+
# - **:open** [Array<Float>] Open prices for each time point
|
|
256
|
+
# - **:high** [Array<Float>] High prices for each time point
|
|
257
|
+
# - **:low** [Array<Float>] Low prices for each time point
|
|
258
|
+
# - **:close** [Array<Float>] Close prices for each time point
|
|
259
|
+
# @return [Hash{Symbol => Array}] Empty hash if option data is not available
|
|
97
260
|
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
98
261
|
def ohlc_data(option_type = nil)
|
|
99
262
|
option_type ||= drv_option_type
|
|
@@ -110,9 +273,12 @@ module DhanHQ
|
|
|
110
273
|
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
111
274
|
|
|
112
275
|
##
|
|
113
|
-
#
|
|
114
|
-
#
|
|
115
|
-
# @
|
|
276
|
+
# Gets volume data for the specified option type.
|
|
277
|
+
#
|
|
278
|
+
# @param option_type [String, nil] Option type to retrieve ("CALL" or "PUT").
|
|
279
|
+
# If nil, uses the {#drv_option_type} from the request.
|
|
280
|
+
# @return [Array<Integer>] Array of volume values traded in each timeframe.
|
|
281
|
+
# Returns empty array if option data is not available or volume was not requested.
|
|
116
282
|
def volume_data(option_type = nil)
|
|
117
283
|
option_type ||= drv_option_type
|
|
118
284
|
option_data = data_for_type(option_type)
|
|
@@ -122,9 +288,12 @@ module DhanHQ
|
|
|
122
288
|
end
|
|
123
289
|
|
|
124
290
|
##
|
|
125
|
-
#
|
|
126
|
-
#
|
|
127
|
-
# @
|
|
291
|
+
# Gets open interest (OI) data for the specified option type.
|
|
292
|
+
#
|
|
293
|
+
# @param option_type [String, nil] Option type to retrieve ("CALL" or "PUT").
|
|
294
|
+
# If nil, uses the {#drv_option_type} from the request.
|
|
295
|
+
# @return [Array<Float>] Array of open interest values for each timeframe.
|
|
296
|
+
# Returns empty array if option data is not available or OI was not requested.
|
|
128
297
|
def open_interest_data(option_type = nil)
|
|
129
298
|
option_type ||= drv_option_type
|
|
130
299
|
option_data = data_for_type(option_type)
|
|
@@ -134,9 +303,12 @@ module DhanHQ
|
|
|
134
303
|
end
|
|
135
304
|
|
|
136
305
|
##
|
|
137
|
-
#
|
|
138
|
-
#
|
|
139
|
-
# @
|
|
306
|
+
# Gets implied volatility (IV) data for the specified option type.
|
|
307
|
+
#
|
|
308
|
+
# @param option_type [String, nil] Option type to retrieve ("CALL" or "PUT").
|
|
309
|
+
# If nil, uses the {#drv_option_type} from the request.
|
|
310
|
+
# @return [Array<Float>] Array of implied volatility values for each timeframe.
|
|
311
|
+
# Returns empty array if option data is not available or IV was not requested.
|
|
140
312
|
def implied_volatility_data(option_type = nil)
|
|
141
313
|
option_type ||= drv_option_type
|
|
142
314
|
option_data = data_for_type(option_type)
|
|
@@ -146,9 +318,12 @@ module DhanHQ
|
|
|
146
318
|
end
|
|
147
319
|
|
|
148
320
|
##
|
|
149
|
-
#
|
|
150
|
-
#
|
|
151
|
-
# @
|
|
321
|
+
# Gets strike price data for the specified option type.
|
|
322
|
+
#
|
|
323
|
+
# @param option_type [String, nil] Option type to retrieve ("CALL" or "PUT").
|
|
324
|
+
# If nil, uses the {#drv_option_type} from the request.
|
|
325
|
+
# @return [Array<Float>] Array of strike prices for each timeframe.
|
|
326
|
+
# Returns empty array if option data is not available or strike was not requested.
|
|
152
327
|
def strike_data(option_type = nil)
|
|
153
328
|
option_type ||= drv_option_type
|
|
154
329
|
option_data = data_for_type(option_type)
|
|
@@ -158,9 +333,12 @@ module DhanHQ
|
|
|
158
333
|
end
|
|
159
334
|
|
|
160
335
|
##
|
|
161
|
-
#
|
|
162
|
-
#
|
|
163
|
-
# @
|
|
336
|
+
# Gets spot price data for the specified option type.
|
|
337
|
+
#
|
|
338
|
+
# @param option_type [String, nil] Option type to retrieve ("CALL" or "PUT").
|
|
339
|
+
# If nil, uses the {#drv_option_type} from the request.
|
|
340
|
+
# @return [Array<Float>] Array of spot prices for each timeframe.
|
|
341
|
+
# Returns empty array if option data is not available or spot was not requested.
|
|
164
342
|
def spot_data(option_type = nil)
|
|
165
343
|
option_type ||= drv_option_type
|
|
166
344
|
option_data = data_for_type(option_type)
|
|
@@ -170,9 +348,12 @@ module DhanHQ
|
|
|
170
348
|
end
|
|
171
349
|
|
|
172
350
|
##
|
|
173
|
-
#
|
|
174
|
-
#
|
|
175
|
-
# @
|
|
351
|
+
# Gets timestamp data for the specified option type.
|
|
352
|
+
#
|
|
353
|
+
# @param option_type [String, nil] Option type to retrieve ("CALL" or "PUT").
|
|
354
|
+
# If nil, uses the {#drv_option_type} from the request.
|
|
355
|
+
# @return [Array<Integer>] Array of epoch timestamps (Unix time in seconds) for each timeframe.
|
|
356
|
+
# Returns empty array if option data is not available.
|
|
176
357
|
def timestamp_data(option_type = nil)
|
|
177
358
|
option_type ||= drv_option_type
|
|
178
359
|
option_data = data_for_type(option_type)
|
|
@@ -182,18 +363,22 @@ module DhanHQ
|
|
|
182
363
|
end
|
|
183
364
|
|
|
184
365
|
##
|
|
185
|
-
#
|
|
186
|
-
#
|
|
187
|
-
# @
|
|
366
|
+
# Gets the number of data points available for the specified option type.
|
|
367
|
+
#
|
|
368
|
+
# @param option_type [String, nil] Option type to retrieve ("CALL" or "PUT").
|
|
369
|
+
# If nil, uses the {#drv_option_type} from the request.
|
|
370
|
+
# @return [Integer] Number of data points (timeframes) available. Returns 0 if no data.
|
|
188
371
|
def data_points_count(option_type = nil)
|
|
189
372
|
timestamps = timestamp_data(option_type)
|
|
190
373
|
timestamps.size
|
|
191
374
|
end
|
|
192
375
|
|
|
193
376
|
##
|
|
194
|
-
#
|
|
195
|
-
#
|
|
196
|
-
# @
|
|
377
|
+
# Calculates the average volume for the specified option type.
|
|
378
|
+
#
|
|
379
|
+
# @param option_type [String, nil] Option type to retrieve ("CALL" or "PUT").
|
|
380
|
+
# If nil, uses the {#drv_option_type} from the request.
|
|
381
|
+
# @return [Float] Average volume across all timeframes. Returns 0.0 if no volume data is available.
|
|
197
382
|
def average_volume(option_type = nil)
|
|
198
383
|
volumes = volume_data(option_type)
|
|
199
384
|
return 0.0 if volumes.empty?
|
|
@@ -202,9 +387,11 @@ module DhanHQ
|
|
|
202
387
|
end
|
|
203
388
|
|
|
204
389
|
##
|
|
205
|
-
#
|
|
206
|
-
#
|
|
207
|
-
# @
|
|
390
|
+
# Calculates the average open interest for the specified option type.
|
|
391
|
+
#
|
|
392
|
+
# @param option_type [String, nil] Option type to retrieve ("CALL" or "PUT").
|
|
393
|
+
# If nil, uses the {#drv_option_type} from the request.
|
|
394
|
+
# @return [Float] Average open interest across all timeframes. Returns 0.0 if no OI data is available.
|
|
208
395
|
def average_open_interest(option_type = nil)
|
|
209
396
|
oi_data = open_interest_data(option_type)
|
|
210
397
|
return 0.0 if oi_data.empty?
|
|
@@ -213,9 +400,11 @@ module DhanHQ
|
|
|
213
400
|
end
|
|
214
401
|
|
|
215
402
|
##
|
|
216
|
-
#
|
|
217
|
-
#
|
|
218
|
-
# @
|
|
403
|
+
# Calculates the average implied volatility for the specified option type.
|
|
404
|
+
#
|
|
405
|
+
# @param option_type [String, nil] Option type to retrieve ("CALL" or "PUT").
|
|
406
|
+
# If nil, uses the {#drv_option_type} from the request.
|
|
407
|
+
# @return [Float] Average implied volatility across all timeframes. Returns 0.0 if no IV data is available.
|
|
219
408
|
def average_implied_volatility(option_type = nil)
|
|
220
409
|
iv_data = implied_volatility_data(option_type)
|
|
221
410
|
return 0.0 if iv_data.empty?
|
|
@@ -224,9 +413,12 @@ module DhanHQ
|
|
|
224
413
|
end
|
|
225
414
|
|
|
226
415
|
##
|
|
227
|
-
#
|
|
228
|
-
#
|
|
229
|
-
# @
|
|
416
|
+
# Calculates price range (high - low) for each timeframe of the specified option type.
|
|
417
|
+
#
|
|
418
|
+
# @param option_type [String, nil] Option type to retrieve ("CALL" or "PUT").
|
|
419
|
+
# If nil, uses the {#drv_option_type} from the request.
|
|
420
|
+
# @return [Array<Float>] Array of price ranges (high - low) for each data point.
|
|
421
|
+
# Returns empty array if OHLC data is not available.
|
|
230
422
|
def price_ranges(option_type = nil)
|
|
231
423
|
ohlc = ohlc_data(option_type)
|
|
232
424
|
highs = ohlc[:high]
|
|
@@ -238,9 +430,20 @@ module DhanHQ
|
|
|
238
430
|
end
|
|
239
431
|
|
|
240
432
|
##
|
|
241
|
-
#
|
|
242
|
-
#
|
|
243
|
-
# @
|
|
433
|
+
# Gets comprehensive summary statistics for the specified option type.
|
|
434
|
+
#
|
|
435
|
+
# @param option_type [String, nil] Option type to retrieve ("CALL" or "PUT").
|
|
436
|
+
# If nil, uses the {#drv_option_type} from the request.
|
|
437
|
+
# @return [Hash{Symbol => Integer, Float, Array, Boolean}] Summary statistics hash containing:
|
|
438
|
+
# - **:data_points** [Integer] Total number of data points
|
|
439
|
+
# - **:avg_volume** [Float] Average volume
|
|
440
|
+
# - **:avg_open_interest** [Float] Average open interest
|
|
441
|
+
# - **:avg_implied_volatility** [Float] Average implied volatility
|
|
442
|
+
# - **:price_ranges** [Array<Float>] Price ranges (high - low) for each point
|
|
443
|
+
# - **:has_ohlc** [Boolean] Whether OHLC data is available
|
|
444
|
+
# - **:has_volume** [Boolean] Whether volume data is available
|
|
445
|
+
# - **:has_open_interest** [Boolean] Whether open interest data is available
|
|
446
|
+
# - **:has_implied_volatility** [Boolean] Whether implied volatility data is available
|
|
244
447
|
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
245
448
|
def summary_stats(option_type = nil)
|
|
246
449
|
option_type ||= drv_option_type
|
|
@@ -264,57 +467,79 @@ module DhanHQ
|
|
|
264
467
|
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
|
265
468
|
|
|
266
469
|
##
|
|
267
|
-
#
|
|
268
|
-
#
|
|
470
|
+
# Checks if this is index options data.
|
|
471
|
+
#
|
|
472
|
+
# @return [Boolean] true if instrument type is "OPTIDX", false otherwise
|
|
269
473
|
def index_options?
|
|
270
474
|
instrument == "OPTIDX"
|
|
271
475
|
end
|
|
272
476
|
|
|
273
477
|
##
|
|
274
|
-
#
|
|
275
|
-
#
|
|
478
|
+
# Checks if this is stock options data.
|
|
479
|
+
#
|
|
480
|
+
# @return [Boolean] true if instrument type is "OPTSTK", false otherwise
|
|
276
481
|
def stock_options?
|
|
277
482
|
instrument == "OPTSTK"
|
|
278
483
|
end
|
|
279
484
|
|
|
280
485
|
##
|
|
281
|
-
#
|
|
282
|
-
#
|
|
486
|
+
# Checks if this is weekly expiry data.
|
|
487
|
+
#
|
|
488
|
+
# @return [Boolean] true if expiry_flag is "WEEK", false otherwise
|
|
283
489
|
def weekly_expiry?
|
|
284
490
|
expiry_flag == "WEEK"
|
|
285
491
|
end
|
|
286
492
|
|
|
287
493
|
##
|
|
288
|
-
#
|
|
289
|
-
#
|
|
494
|
+
# Checks if this is monthly expiry data.
|
|
495
|
+
#
|
|
496
|
+
# @return [Boolean] true if expiry_flag is "MONTH", false otherwise
|
|
290
497
|
def monthly_expiry?
|
|
291
498
|
expiry_flag == "MONTH"
|
|
292
499
|
end
|
|
293
500
|
|
|
294
501
|
##
|
|
295
|
-
#
|
|
296
|
-
#
|
|
502
|
+
# Checks if this is call option data.
|
|
503
|
+
#
|
|
504
|
+
# @return [Boolean] true if drv_option_type is "CALL", false otherwise
|
|
297
505
|
def call_option?
|
|
298
506
|
drv_option_type == "CALL"
|
|
299
507
|
end
|
|
300
508
|
|
|
301
509
|
##
|
|
302
|
-
#
|
|
303
|
-
#
|
|
510
|
+
# Checks if this is put option data.
|
|
511
|
+
#
|
|
512
|
+
# @return [Boolean] true if drv_option_type is "PUT", false otherwise
|
|
304
513
|
def put_option?
|
|
305
514
|
drv_option_type == "PUT"
|
|
306
515
|
end
|
|
307
516
|
|
|
308
517
|
##
|
|
309
|
-
#
|
|
310
|
-
#
|
|
518
|
+
# Checks if the strike is at the money (ATM).
|
|
519
|
+
#
|
|
520
|
+
# @return [Boolean] true if strike is "ATM", false otherwise
|
|
311
521
|
def at_the_money?
|
|
312
522
|
strike == "ATM"
|
|
313
523
|
end
|
|
314
524
|
|
|
315
525
|
##
|
|
316
|
-
#
|
|
317
|
-
#
|
|
526
|
+
# Calculates the strike offset from ATM (At The Money).
|
|
527
|
+
#
|
|
528
|
+
# @return [Integer] Strike offset value:
|
|
529
|
+
# - 0 for ATM strikes
|
|
530
|
+
# - Positive integer for ATM+X (e.g., ATM+3 returns 3)
|
|
531
|
+
# - Negative integer for ATM-X (e.g., ATM-2 returns -2)
|
|
532
|
+
# - 0 if strike format is invalid
|
|
533
|
+
#
|
|
534
|
+
# @example
|
|
535
|
+
# data.strike = "ATM+5"
|
|
536
|
+
# data.strike_offset # => 5
|
|
537
|
+
#
|
|
538
|
+
# data.strike = "ATM-3"
|
|
539
|
+
# data.strike_offset # => -3
|
|
540
|
+
#
|
|
541
|
+
# data.strike = "ATM"
|
|
542
|
+
# data.strike_offset # => 0
|
|
318
543
|
def strike_offset
|
|
319
544
|
return 0 if at_the_money?
|
|
320
545
|
|