Class: DhanHQ::Models::ExpiredOptionsData

Inherits:
BaseModel
  • Object
show all
Defined in:
lib/DhanHQ/models/expired_options_data.rb

Overview

Model for fetching expired options contract data on a rolling basis.

This API provides pre-processed expired options data for up to the last 5 years. Data is available on a minute-level basis, organized by strike price relative to spot (e.g., ATM, ATM+1, ATM-1, etc.). You can fetch up to 31 days of data in a single API call.

Available data includes:

  • OHLC (Open, High, Low, Close) prices

  • Volume and Open Interest

  • Implied Volatility (IV)

  • Strike prices

  • Spot prices

  • Timestamps

Strike ranges:

  • Index Options (near expiry): Up to ATM+10 / ATM-10

  • All other contracts: Up to ATM+3 / ATM-3

rubocop:disable Metrics/ClassLength

Examples:

Fetch expired options data for NIFTY

data = DhanHQ::Models::ExpiredOptionsData.fetch(
  exchange_segment: "NSE_FNO",
  interval: "1",
  security_id: 13,
  instrument: "OPTIDX",
  expiry_flag: "MONTH",
  expiry_code: 1,
  strike: "ATM",
  drv_option_type: "CALL",
  required_data: ["open", "high", "low", "close", "volume"],
  from_date: "2021-08-01",
  to_date: "2021-09-01"
)
ohlc = data.ohlc_data
volumes = data.volume_data

Access call option data

call_data = data.call_data
put_data = data.put_data

Instance Attribute Summary

Attributes inherited from BaseModel

#attributes, #errors

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from BaseModel

all, api, api_type, #assign_attributes, attributes, create, #delete, #destroy, find, #id, #initialize, #new_record?, #optionchain_api?, parse_collection_response, #persisted?, resource, resource_path, #save, #save!, #to_request_params, #update, #valid?, validate_attributes, validation_contract, where

Methods included from APIHelper

#handle_response

Methods included from AttributeHelper

#camelize_keys, #inspect, #normalize_keys, #snake_case, #titleize_keys

Methods included from ValidationHelper

#valid?, #validate!, #validate_params!

Methods included from RequestHelper

#build_from_response

Constructor Details

This class inherits a constructor from DhanHQ::BaseModel

Class Method Details

.fetch(params) ⇒ ExpiredOptionsData

Fetches expired options data for rolling contracts on a minute-level basis.

Data is organized by strike price relative to spot and can be fetched for up to 31 days in a single request. Historical data is available for up to the last 5 years.

Examples:

Fetch NIFTY index options data

data = DhanHQ::Models::ExpiredOptionsData.fetch(
  exchange_segment: "NSE_FNO",
  interval: "1",
  security_id: 13,
  instrument: "OPTIDX",
  expiry_flag: "MONTH",
  expiry_code: 1,
  strike: "ATM",
  drv_option_type: "CALL",
  required_data: ["open", "high", "low", "close", "volume", "iv", "oi", "spot"],
  from_date: "2021-08-01",
  to_date: "2021-09-01"
)

Fetch stock options data for ATM+2 strike

data = DhanHQ::Models::ExpiredOptionsData.fetch(
  exchange_segment: "NSE_FNO",
  interval: "15",
  security_id: 11536,
  instrument: "OPTSTK",
  expiry_flag: "WEEK",
  expiry_code: 0,
  strike: "ATM+2",
  drv_option_type: "PUT",
  required_data: ["open", "high", "low", "close", "volume"],
  from_date: "2024-01-01",
  to_date: "2024-01-31"
)

Parameters:

  • params (Hash{Symbol => String, Integer, Array<String>})

    Request parameters @option params [String] :exchange_segment (required) Exchange and segment identifier.

    Valid values: "NSE_FNO", "BSE_FNO", "NSE_EQ", "BSE_EQ"
    

    @option params [String] :interval (required) Minute intervals for the timeframe.

    Valid values: "1", "5", "15", "25", "60"
    

    @option params [Integer] :security_id (required) Underlying exchange standard ID for each scrip @option params [String] :instrument (required) Instrument type of the scrip.

    Valid values: "OPTIDX" (Index Options), "OPTSTK" (Stock Options)
    

    @option params [String] :expiry_flag (required) Expiry interval of the instrument.

    Valid values: "WEEK", "MONTH"
    

    @option params [Integer] :expiry_code (required) Expiry code for the instrument @option params [String] :strike (required) Strike price specification.

    Format: "ATM" for At The Money, "ATM+X" or "ATM-X" for offset strikes.
    For Index Options (near expiry): Up to ATM+10 / ATM-10
    For all other contracts: Up to ATM+3 / ATM-3
    

    @option params [String] :drv_option_type (required) Option type.

    Valid values: "CALL", "PUT"
    

    @option params [Array<String>] :required_data (required) Array of required data fields.

    Valid values: "open", "high", "low", "close", "iv", "volume", "strike", "oi", "spot"
    

    @option params [String] :from_date (required) Start date of the desired range in YYYY-MM-DD format.

    Cannot be more than 5 years ago. Same-day ranges are allowed.
    

    @option params [String] :to_date (required) End date of the desired range (non-inclusive) in YYYY-MM-DD format.

    Date range cannot exceed 31 days from from_date (to_date is non-inclusive). Same-day `from_date`/`to_date` is valid.
    

Returns:

Raises:



116
117
118
119
120
121
122
# File 'lib/DhanHQ/models/expired_options_data.rb', line 116

def fetch(params)
  normalized = normalize_params(params)
  validate_params(normalized)

  response = expired_options_resource.fetch(normalized)
  new(response.merge(normalized), skip_validation: true)
end

Instance Method Details

#at_the_money?Boolean

Checks if the strike is at the money (ATM).

Returns:

  • (Boolean)

    true if strike is “ATM”, false otherwise



521
522
523
# File 'lib/DhanHQ/models/expired_options_data.rb', line 521

def at_the_money?
  strike == "ATM"
end

#average_implied_volatility(option_type = nil) ⇒ Float

Calculates the average implied volatility for the specified option type.

Parameters:

  • option_type (String, nil) (defaults to: nil)

    Option type to retrieve (“CALL” or “PUT”). If nil, uses the #drv_option_type from the request.

Returns:

  • (Float)

    Average implied volatility across all timeframes. Returns 0.0 if no IV data is available.



408
409
410
411
412
413
# File 'lib/DhanHQ/models/expired_options_data.rb', line 408

def average_implied_volatility(option_type = nil)
  iv_data = implied_volatility_data(option_type)
  return 0.0 if iv_data.empty?

  iv_data.sum.to_f / iv_data.size
end

#average_open_interest(option_type = nil) ⇒ Float

Calculates the average open interest for the specified option type.

Parameters:

  • option_type (String, nil) (defaults to: nil)

    Option type to retrieve (“CALL” or “PUT”). If nil, uses the #drv_option_type from the request.

Returns:

  • (Float)

    Average open interest across all timeframes. Returns 0.0 if no OI data is available.



395
396
397
398
399
400
# File 'lib/DhanHQ/models/expired_options_data.rb', line 395

def average_open_interest(option_type = nil)
  oi_data = open_interest_data(option_type)
  return 0.0 if oi_data.empty?

  oi_data.sum.to_f / oi_data.size
end

#average_volume(option_type = nil) ⇒ Float

Calculates the average volume for the specified option type.

Parameters:

  • option_type (String, nil) (defaults to: nil)

    Option type to retrieve (“CALL” or “PUT”). If nil, uses the #drv_option_type from the request.

Returns:

  • (Float)

    Average volume across all timeframes. Returns 0.0 if no volume data is available.



382
383
384
385
386
387
# File 'lib/DhanHQ/models/expired_options_data.rb', line 382

def average_volume(option_type = nil)
  volumes = volume_data(option_type)
  return 0.0 if volumes.empty?

  volumes.sum.to_f / volumes.size
end

#call_dataHash{Symbol => Array<Float, Integer>}?

Gets call option data from the response.

Returns:

  • (Hash{Symbol => Array<Float, Integer>}, nil)

    Call option data hash containing arrays of OHLC, volume, IV, OI, strike, spot, and timestamps. Returns nil if call option data is not available in the response. Keys are normalized to snake_case:

    • :open [Array<Float>] Open prices

    • :high [Array<Float>] High prices

    • :low [Array<Float>] Low prices

    • :close [Array<Float>] Close prices

    • :volume [Array<Integer>] Volume traded

    • :iv [Array<Float>] Implied volatility values

    • :oi [Array<Float>] Open interest values

    • :strike [Array<Float>] Strike prices

    • :spot [Array<Float>] Spot prices

    • :timestamp [Array<Integer>] Epoch timestamps



206
207
208
209
210
# File 'lib/DhanHQ/models/expired_options_data.rb', line 206

def call_data
  return nil unless data.is_a?(Hash)

  data["ce"] || data[:ce]
end

#call_option?Boolean

Checks if this is call option data.

Returns:

  • (Boolean)

    true if drv_option_type is “CALL”, false otherwise



505
506
507
# File 'lib/DhanHQ/models/expired_options_data.rb', line 505

def call_option?
  drv_option_type == "CALL"
end

#data_for_type(option_type) ⇒ Hash{Symbol => Array<Float, Integer>}?

Gets data for the specified option type.

Parameters:

  • option_type (String)

    Option type to retrieve. Valid values: “CALL”, “PUT”

Returns:

  • (Hash{Symbol => Array<Float, Integer>}, nil)

    Option data hash or nil if not available. See #call_data or #put_data for structure details.



240
241
242
243
244
245
246
247
# File 'lib/DhanHQ/models/expired_options_data.rb', line 240

def data_for_type(option_type)
  case option_type.upcase
  when "CALL"
    call_data
  when "PUT"
    put_data
  end
end

#data_points_count(option_type = nil) ⇒ Integer

Gets the number of data points available for the specified option type.

Parameters:

  • option_type (String, nil) (defaults to: nil)

    Option type to retrieve (“CALL” or “PUT”). If nil, uses the #drv_option_type from the request.

Returns:

  • (Integer)

    Number of data points (timeframes) available. Returns 0 if no data.



371
372
373
374
# File 'lib/DhanHQ/models/expired_options_data.rb', line 371

def data_points_count(option_type = nil)
  timestamps = timestamp_data(option_type)
  timestamps.size
end

#implied_volatility_data(option_type = nil) ⇒ Array<Float>

Gets implied volatility (IV) data for the specified option type.

Parameters:

  • option_type (String, nil) (defaults to: nil)

    Option type to retrieve (“CALL” or “PUT”). If nil, uses the #drv_option_type from the request.

Returns:

  • (Array<Float>)

    Array of implied volatility values for each timeframe. Returns empty array if option data is not available or IV was not requested.



312
313
314
315
316
317
318
# File 'lib/DhanHQ/models/expired_options_data.rb', line 312

def implied_volatility_data(option_type = nil)
  option_type ||= drv_option_type
  option_data = data_for_type(option_type)
  return [] unless option_data

  option_data["iv"] || option_data[:iv] || []
end

#index_options?Boolean

Checks if this is index options data.

Returns:

  • (Boolean)

    true if instrument type is “OPTIDX”, false otherwise



473
474
475
# File 'lib/DhanHQ/models/expired_options_data.rb', line 473

def index_options?
  instrument == "OPTIDX"
end

#monthly_expiry?Boolean

Checks if this is monthly expiry data.

Returns:

  • (Boolean)

    true if expiry_flag is “MONTH”, false otherwise



497
498
499
# File 'lib/DhanHQ/models/expired_options_data.rb', line 497

def monthly_expiry?
  expiry_flag == "MONTH"
end

#ohlc_data(option_type = nil) ⇒ Hash{Symbol => Array<Float>}, Hash{Symbol => Array}

Gets OHLC (Open, High, Low, Close) data for the specified option type.

rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity

Parameters:

  • option_type (String, nil) (defaults to: nil)

    Option type to retrieve (“CALL” or “PUT”). If nil, uses the #drv_option_type from the request.

Returns:

  • (Hash{Symbol => Array<Float>})

    OHLC data hash with:

    • :open [Array<Float>] Open prices for each time point

    • :high [Array<Float>] High prices for each time point

    • :low [Array<Float>] Low prices for each time point

    • :close [Array<Float>] Close prices for each time point

  • (Hash{Symbol => Array})

    Empty hash if option data is not available



261
262
263
264
265
266
267
268
269
270
271
272
# File 'lib/DhanHQ/models/expired_options_data.rb', line 261

def ohlc_data(option_type = nil)
  option_type ||= drv_option_type
  option_data = data_for_type(option_type)
  return {} unless option_data

  {
    open: option_data["open"] || option_data[:open] || [],
    high: option_data["high"] || option_data[:high] || [],
    low: option_data["low"] || option_data[:low] || [],
    close: option_data["close"] || option_data[:close] || []
  }
end

#open_interest_data(option_type = nil) ⇒ Array<Float>

Gets open interest (OI) data for the specified option type.

Parameters:

  • option_type (String, nil) (defaults to: nil)

    Option type to retrieve (“CALL” or “PUT”). If nil, uses the #drv_option_type from the request.

Returns:

  • (Array<Float>)

    Array of open interest values for each timeframe. Returns empty array if option data is not available or OI was not requested.



297
298
299
300
301
302
303
# File 'lib/DhanHQ/models/expired_options_data.rb', line 297

def open_interest_data(option_type = nil)
  option_type ||= drv_option_type
  option_data = data_for_type(option_type)
  return [] unless option_data

  option_data["oi"] || option_data[:oi] || []
end

#price_ranges(option_type = nil) ⇒ Array<Float>

Calculates price range (high - low) for each timeframe of the specified option type.

Parameters:

  • option_type (String, nil) (defaults to: nil)

    Option type to retrieve (“CALL” or “PUT”). If nil, uses the #drv_option_type from the request.

Returns:

  • (Array<Float>)

    Array of price ranges (high - low) for each data point. Returns empty array if OHLC data is not available.



422
423
424
425
426
427
428
429
430
# File 'lib/DhanHQ/models/expired_options_data.rb', line 422

def price_ranges(option_type = nil)
  ohlc = ohlc_data(option_type)
  highs = ohlc[:high]
  lows = ohlc[:low]

  return [] if highs.empty? || lows.empty?

  highs.zip(lows).map { |high, low| high - low }
end

#put_dataHash{Symbol => Array<Float, Integer>}?

Gets put option data from the response.

Returns:

  • (Hash{Symbol => Array<Float, Integer>}, nil)

    Put option data hash containing arrays of OHLC, volume, IV, OI, strike, spot, and timestamps. Returns nil if put option data is not available in the response. Keys are normalized to snake_case:

    • :open [Array<Float>] Open prices

    • :high [Array<Float>] High prices

    • :low [Array<Float>] Low prices

    • :close [Array<Float>] Close prices

    • :volume [Array<Integer>] Volume traded

    • :iv [Array<Float>] Implied volatility values

    • :oi [Array<Float>] Open interest values

    • :strike [Array<Float>] Strike prices

    • :spot [Array<Float>] Spot prices

    • :timestamp [Array<Integer>] Epoch timestamps



228
229
230
231
232
# File 'lib/DhanHQ/models/expired_options_data.rb', line 228

def put_data
  return nil unless data.is_a?(Hash)

  data["pe"] || data[:pe]
end

#put_option?Boolean

Checks if this is put option data.

Returns:

  • (Boolean)

    true if drv_option_type is “PUT”, false otherwise



513
514
515
# File 'lib/DhanHQ/models/expired_options_data.rb', line 513

def put_option?
  drv_option_type == "PUT"
end

#spot_data(option_type = nil) ⇒ Array<Float>

Gets spot price data for the specified option type.

Parameters:

  • option_type (String, nil) (defaults to: nil)

    Option type to retrieve (“CALL” or “PUT”). If nil, uses the #drv_option_type from the request.

Returns:

  • (Array<Float>)

    Array of spot prices for each timeframe. Returns empty array if option data is not available or spot was not requested.



342
343
344
345
346
347
348
# File 'lib/DhanHQ/models/expired_options_data.rb', line 342

def spot_data(option_type = nil)
  option_type ||= drv_option_type
  option_data = data_for_type(option_type)
  return [] unless option_data

  option_data["spot"] || option_data[:spot] || []
end

#stock_options?Boolean

Checks if this is stock options data.

Returns:

  • (Boolean)

    true if instrument type is “OPTSTK”, false otherwise



481
482
483
# File 'lib/DhanHQ/models/expired_options_data.rb', line 481

def stock_options?
  instrument == "OPTSTK"
end

#strike_data(option_type = nil) ⇒ Array<Float>

Gets strike price data for the specified option type.

Parameters:

  • option_type (String, nil) (defaults to: nil)

    Option type to retrieve (“CALL” or “PUT”). If nil, uses the #drv_option_type from the request.

Returns:

  • (Array<Float>)

    Array of strike prices for each timeframe. Returns empty array if option data is not available or strike was not requested.



327
328
329
330
331
332
333
# File 'lib/DhanHQ/models/expired_options_data.rb', line 327

def strike_data(option_type = nil)
  option_type ||= drv_option_type
  option_data = data_for_type(option_type)
  return [] unless option_data

  option_data["strike"] || option_data[:strike] || []
end

#strike_offsetInteger

Calculates the strike offset from ATM (At The Money).

Examples:

data.strike = "ATM+5"
data.strike_offset # => 5

data.strike = "ATM-3"
data.strike_offset # => -3

data.strike = "ATM"
data.strike_offset # => 0

Returns:

  • (Integer)

    Strike offset value:

    • 0 for ATM strikes

    • Positive integer for ATM+X (e.g., ATM+3 returns 3)

    • Negative integer for ATM-X (e.g., ATM-2 returns -2)

    • 0 if strike format is invalid



543
544
545
546
547
548
549
550
551
552
# File 'lib/DhanHQ/models/expired_options_data.rb', line 543

def strike_offset
  return 0 if at_the_money?

  match = strike.match(/\AATM(\+|-)?(\d+)\z/)
  return 0 unless match

  sign = match[1] == "-" ? -1 : 1
  offset = match[2].to_i
  sign * offset
end

#summary_stats(option_type = nil) ⇒ Hash{Symbol => Integer, Float, Array, Boolean}

Gets comprehensive summary statistics for the specified option type.

rubocop:disable Metrics/AbcSize, Metrics/MethodLength

Parameters:

  • option_type (String, nil) (defaults to: nil)

    Option type to retrieve (“CALL” or “PUT”). If nil, uses the #drv_option_type from the request.

Returns:

  • (Hash{Symbol => Integer, Float, Array, Boolean})

    Summary statistics hash containing:

    • :data_points [Integer] Total number of data points

    • :avg_volume [Float] Average volume

    • :avg_open_interest [Float] Average open interest

    • :avg_implied_volatility [Float] Average implied volatility

    • :price_ranges [Array<Float>] Price ranges (high - low) for each point

    • :has_ohlc [Boolean] Whether OHLC data is available

    • :has_volume [Boolean] Whether volume data is available

    • :has_open_interest [Boolean] Whether open interest data is available

    • :has_implied_volatility [Boolean] Whether implied volatility data is available



448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
# File 'lib/DhanHQ/models/expired_options_data.rb', line 448

def summary_stats(option_type = nil)
  option_type ||= drv_option_type
  ohlc = ohlc_data(option_type)
  volumes = volume_data(option_type)
  oi_data = open_interest_data(option_type)
  iv_data = implied_volatility_data(option_type)

  {
    data_points: data_points_count(option_type),
    avg_volume: average_volume(option_type),
    avg_open_interest: average_open_interest(option_type),
    avg_implied_volatility: average_implied_volatility(option_type),
    price_ranges: price_ranges(option_type),
    has_ohlc: !ohlc[:open].empty?,
    has_volume: !volumes.empty?,
    has_open_interest: !oi_data.empty?,
    has_implied_volatility: !iv_data.empty?
  }
end

#timestamp_data(option_type = nil) ⇒ Array<Integer>

Gets timestamp data for the specified option type.

Parameters:

  • option_type (String, nil) (defaults to: nil)

    Option type to retrieve (“CALL” or “PUT”). If nil, uses the #drv_option_type from the request.

Returns:

  • (Array<Integer>)

    Array of epoch timestamps (Unix time in seconds) for each timeframe. Returns empty array if option data is not available.



357
358
359
360
361
362
363
# File 'lib/DhanHQ/models/expired_options_data.rb', line 357

def timestamp_data(option_type = nil)
  option_type ||= drv_option_type
  option_data = data_for_type(option_type)
  return [] unless option_data

  option_data["timestamp"] || option_data[:timestamp] || []
end

#validation_contractObject

ExpiredOptionsData objects are read-only, so no validation contract needed



186
187
188
# File 'lib/DhanHQ/models/expired_options_data.rb', line 186

def validation_contract
  nil
end

#volume_data(option_type = nil) ⇒ Array<Integer>

Gets volume data for the specified option type.

Parameters:

  • option_type (String, nil) (defaults to: nil)

    Option type to retrieve (“CALL” or “PUT”). If nil, uses the #drv_option_type from the request.

Returns:

  • (Array<Integer>)

    Array of volume values traded in each timeframe. Returns empty array if option data is not available or volume was not requested.



282
283
284
285
286
287
288
# File 'lib/DhanHQ/models/expired_options_data.rb', line 282

def volume_data(option_type = nil)
  option_type ||= drv_option_type
  option_data = data_for_type(option_type)
  return [] unless option_data

  option_data["volume"] || option_data[:volume] || []
end

#weekly_expiry?Boolean

Checks if this is weekly expiry data.

Returns:

  • (Boolean)

    true if expiry_flag is “WEEK”, false otherwise



489
490
491
# File 'lib/DhanHQ/models/expired_options_data.rb', line 489

def weekly_expiry?
  expiry_flag == "WEEK"
end