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