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.
@@ -3,8 +3,45 @@
3
3
  module DhanHQ
4
4
  module Models
5
5
  ##
6
- # Represents expired options data for rolling contracts
7
- # Provides access to OHLC, volume, open interest, implied volatility, and spot data
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
- # Fetch expired options data for rolling contracts
18
- # POST /charts/rollingoption
54
+ # Fetches expired options data for rolling contracts on a minute-level basis.
19
55
  #
20
- # @param params [Hash] Parameters for the request
21
- # @option params [String] :exchange_segment Exchange segment (e.g., "NSE_FNO")
22
- # @option params [Integer] :interval Minute interval (1, 5, 15, 25, 60)
23
- # @option params [String] :security_id Security ID for the underlying
24
- # @option params [String] :instrument Instrument type ("OPTIDX" or "OPTSTK")
25
- # @option params [String] :expiry_flag Expiry interval ("WEEK" or "MONTH")
26
- # @option params [Integer] :expiry_code Expiry code
27
- # @option params [String] :strike Strike price ("ATM", "ATM+1", "ATM-1", etc.)
28
- # @option params [String] :drv_option_type Option type ("CALL" or "PUT")
29
- # @option params [Array<String>] :required_data Required data fields
30
- # @option params [String] :from_date Start date (YYYY-MM-DD)
31
- # @option params [String] :to_date End date (YYYY-MM-DD)
32
- # @return [ExpiredOptionsData] Expired options data object
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
- validate_params(params)
117
+ normalized = normalize_params(params)
118
+ validate_params(normalized)
35
119
 
36
- response = expired_options_resource.fetch(params)
37
- new(response.merge(params), skip_validation: true)
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
- # Get call option data
64
- # @return [Hash, nil] Call option data or nil if not available
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
- # Get put option data
73
- # @return [Hash, nil] Put option data or nil if not available
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
- # Get data for the specified option type
82
- # @param option_type [String] "CALL" or "PUT"
83
- # @return [Hash, nil] Option data or nil if not available
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
- # Get OHLC data for the specified option type
95
- # @param option_type [String] "CALL" or "PUT"
96
- # @return [Hash] OHLC data with open, high, low, close arrays
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
- # Get volume data for the specified option type
114
- # @param option_type [String] "CALL" or "PUT"
115
- # @return [Array<Integer>] Volume data array
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
- # Get open interest data for the specified option type
126
- # @param option_type [String] "CALL" or "PUT"
127
- # @return [Array<Float>] Open interest data array
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
- # Get implied volatility data for the specified option type
138
- # @param option_type [String] "CALL" or "PUT"
139
- # @return [Array<Float>] Implied volatility data array
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
- # Get strike price data for the specified option type
150
- # @param option_type [String] "CALL" or "PUT"
151
- # @return [Array<Float>] Strike price data array
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
- # Get spot price data for the specified option type
162
- # @param option_type [String] "CALL" or "PUT"
163
- # @return [Array<Float>] Spot price data array
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
- # Get timestamp data for the specified option type
174
- # @param option_type [String] "CALL" or "PUT"
175
- # @return [Array<Integer>] Timestamp data array (epoch)
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
- # Get data points count for the specified option type
186
- # @param option_type [String] "CALL" or "PUT"
187
- # @return [Integer] Number of data points
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
- # Get average volume for the specified option type
195
- # @param option_type [String] "CALL" or "PUT"
196
- # @return [Float] Average volume
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
- # Get average open interest for the specified option type
206
- # @param option_type [String] "CALL" or "PUT"
207
- # @return [Float] Average open interest
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
- # Get average implied volatility for the specified option type
217
- # @param option_type [String] "CALL" or "PUT"
218
- # @return [Float] Average implied volatility
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
- # Get price range (high - low) for the specified option type
228
- # @param option_type [String] "CALL" or "PUT"
229
- # @return [Array<Float>] Price range for each data point
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
- # Get summary statistics for the specified option type
242
- # @param option_type [String] "CALL" or "PUT"
243
- # @return [Hash] Summary statistics
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
- # Check if this is index options data
268
- # @return [Boolean] true if instrument is OPTIDX
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
- # Check if this is stock options data
275
- # @return [Boolean] true if instrument is OPTSTK
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
- # Check if this is weekly expiry
282
- # @return [Boolean] true if expiry_flag is WEEK
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
- # Check if this is monthly expiry
289
- # @return [Boolean] true if expiry_flag is MONTH
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
- # Check if this is call option data
296
- # @return [Boolean] true if drv_option_type is CALL
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
- # Check if this is put option data
303
- # @return [Boolean] true if drv_option_type is PUT
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
- # Check if strike is at the money
310
- # @return [Boolean] true if strike is ATM
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
- # Get strike offset from ATM
317
- # @return [Integer] Strike offset (0 for ATM, positive for ATM+X, negative for ATM-X)
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