Class: DhanHQ::Models::Position

Inherits:
BaseModel show all
Defined in:
lib/DhanHQ/models/position.rb

Overview

Model for managing intraday and carry-forward positions.

The Positions API lets you retrieve a list of all open positions for the day. This includes all F&O carryforward positions as well. You can also convert positions between product types (e.g., intraday to delivery or vice versa).

Examples:

Fetch all positions

positions = DhanHQ::Models::Position.all
positions.each do |position|
  puts "#{position.trading_symbol}: #{position.net_qty} @ ₹#{position.buy_avg}"
  puts "Unrealized P&L: ₹#{position.unrealized_profit}"
end

Fetch only active (open) positions

open_positions = DhanHQ::Models::Position.active
long_positions = open_positions.select { |p| p.position_type == "LONG" }
puts "Open long positions: #{long_positions.count}"

Convert intraday position to delivery

response = DhanHQ::Models::Position.convert(
  dhan_client_id: "1000000009",
  from_product_type: "INTRADAY",
  to_product_type: "CNC",
  exchange_segment: "NSE_EQ",
  position_type: "LONG",
  security_id: "11536",
  convert_qty: 40
)

Constant Summary collapse

HTTP_PATH =

Base path used by the positions resource.

"/v2/positions"

Constants included from ResponseHelper

ResponseHelper::STATUS_ERROR_FALLBACK

Instance Attribute Summary

Attributes inherited from BaseModel

#attributes, #errors

Class Method Summary collapse

Methods inherited from BaseModel

api, api_type, #assign_attributes, attributes, create, #delete, #destroy, find, #id, #initialize, #new_record?, #optionchain_api?, parse_collection_response, #persisted?, resource_path, #save, #save!, #to_request_params, #update, #valid?, validate_attributes, validation_contract, #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

.activeArray<Position>

Filters the position list to return only active (open) positions.

Removes positions with “CLOSED” status, returning only positions that are currently open (LONG or SHORT positions).

Examples:

Fetch only open positions

open_positions = DhanHQ::Models::Position.active
puts "Open positions: #{open_positions.count}"
open_positions.each do |position|
  puts "#{position.trading_symbol}: #{position.net_qty} (#{position.position_type})"
end

Calculate total open position value

open_positions = DhanHQ::Models::Position.active
total_value = open_positions.sum { |p| p.net_qty * p.buy_avg }
puts "Total open position value: ₹#{total_value}"

Returns:

  • (Array<Position>)

    Array of active Position objects. Excludes positions with position_type “CLOSED”



141
142
143
# File 'lib/DhanHQ/models/position.rb', line 141

def active
  all.reject { |position| position.position_type == DhanHQ::Constants::OrderStatus::CLOSED }
end

.allArray<Position>

Retrieves all positions for the current trading day.

Fetches a list of all open positions including F&O carryforward positions. Returns both active (LONG/SHORT) and closed positions. Use active if you only need open positions.

Examples:

Fetch and analyze positions

positions = DhanHQ::Models::Position.all
total_unrealized = positions.sum(&:unrealized_profit)
total_realized = positions.sum(&:realized_profit)
puts "Total Unrealized P&L: ₹#{total_unrealized}"
puts "Total Realized P&L: ₹#{total_realized}"

Analyze F&O positions

positions = DhanHQ::Models::Position.all
fno_positions = positions.select { |p| p.exchange_segment.include?("FNO") }
fno_positions.each do |pos|
  puts "#{pos.trading_symbol} - Net: #{pos.net_qty}, P&L: ₹#{pos.unrealized_profit}"
end

Returns:

  • (Array<Position>)

    Array of Position objects. Returns empty array if no positions exist. Each Position object contains (keys normalized to snake_case):

    • :dhan_client_id [String] User-specific identification generated by Dhan

    • :trading_symbol [String] Trading symbol of the instrument

    • :security_id [String] Exchange standard ID for each scrip

    • :position_type [String] Position type. Valid values: “LONG”, “SHORT”, “CLOSED”

    • :exchange_segment [String] Exchange and segment. Valid values: “NSE_EQ”, “NSE_FNO”, “NSE_CURRENCY”, “BSE_EQ”, “BSE_FNO”, “BSE_CURRENCY”, “MCX_COMM”

    • :product_type [String] Product type. Valid values: “CNC”, “INTRADAY”, “MARGIN”, “MTF”, “CO”, “BO”

    • :buy_avg [Float] Average buy price mark to market

    • :buy_qty [Integer] Total quantity bought

    • :cost_price [Float] Actual cost price

    • :sell_avg [Float] Average sell price mark to market

    • :sell_qty [Integer] Total quantities sold

    • :net_qty [Integer] Net quantity (buy_qty - sell_qty)

    • :realized_profit [Float] Profit or loss booked

    • :unrealized_profit [Float] Profit or loss standing for open position

    • :rbi_reference_rate [Float] RBI mandated reference rate for forex

    • :multiplier [Integer] Multiplying factor for currency F&O

    • :carry_forward_buy_qty [Integer] Carry forward F&O long quantities

    • :carry_forward_sell_qty [Integer] Carry forward F&O short quantities

    • :carry_forward_buy_value [Float] Carry forward F&O long value

    • :carry_forward_sell_value [Float] Carry forward F&O short value

    • :day_buy_qty [Integer] Quantities bought today

    • :day_sell_qty [Integer] Quantities sold today

    • :day_buy_value [Float] Value of quantities bought today

    • :day_sell_value [Float] Value of quantities sold today

    • :drv_expiry_date [String] For F&O, expiry date of contract (format: “YYYY-MM-DD”)

    • :drv_option_type [String, nil] Type of Option. “CALL” or “PUT”

    • :drv_strike_price [Float] For Options, Strike Price

    • :cross_currency [Boolean] Check for non INR currency pair



111
112
113
114
115
116
117
118
# File 'lib/DhanHQ/models/position.rb', line 111

def all
  response = resource.all
  return [] unless response.is_a?(Array)

  response.map do |position|
    new(snake_case(position), skip_validation: true)
  end
end

.convert(params) ⇒ Hash, DhanHQ::ErrorObject

Note:

The API returns HTTP 202 Accepted on successful conversion

Converts an existing position from one product type to another.

Allows conversion between eligible product types, most commonly between intraday (INTRADAY) and delivery (CNC) positions. This is useful when you want to hold an intraday position overnight or convert a delivery position to intraday.

Examples:

Convert intraday position to delivery

response = DhanHQ::Models::Position.convert(
  dhan_client_id: "1000000009",
  from_product_type: "INTRADAY",
  to_product_type: "CNC",
  exchange_segment: "NSE_EQ",
  position_type: "LONG",
  security_id: "11536",
  convert_qty: 40
)
if response.is_a?(DhanHQ::ErrorObject)
  puts "Conversion failed: #{response.errors}"
else
  puts "Position converted successfully"
end

Convert delivery position to intraday

response = DhanHQ::Models::Position.convert(
  dhan_client_id: "1000000009",
  from_product_type: "CNC",
  to_product_type: "INTRADAY",
  exchange_segment: "NSE_EQ",
  position_type: "LONG",
  security_id: "11536",
  convert_qty: 10
)

Parameters:

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

    Position conversion parameters @option params [String] :dhan_client_id (required) User-specific identification generated by Dhan.

    Must be explicitly provided in the params hash
    

    @option params [String] :from_product_type (required) Current product type of the position.

    Valid values: "CNC", "INTRADAY", "MARGIN", "CO", "BO"
    

    @option params [String] :to_product_type (required) Desired product type after conversion.

    Valid values: "CNC", "INTRADAY", "MARGIN", "CO", "BO"
    Must be different from from_product_type
    

    @option params [String] :exchange_segment (required) Exchange and segment in which position is created.

    Valid values: See {DhanHQ::Constants::EXCHANGE_SEGMENTS}
    

    @option params [String] :position_type (required) Position type to convert.

    Valid values: "LONG", "SHORT", "CLOSED"
    

    @option params [String] :security_id (required) Exchange standard ID for each scrip @option params [String] :trading_symbol (optional) Trading symbol of the instrument @option params [Integer] :convert_qty (required) Number of shares for which conversion is desired.

    Must be greater than 0
    

Returns:

  • (Hash, DhanHQ::ErrorObject)

    API response hash (typically HTTP 202 Accepted) on success, ErrorObject on failure

Raises:



201
202
203
204
205
206
207
# File 'lib/DhanHQ/models/position.rb', line 201

def convert(params)
  formatted_params = camelize_keys(params)
  validate_params!(formatted_params, DhanHQ::Contracts::PositionConversionContract)

  response = resource.convert(formatted_params)
  success_response?(response) ? response : DhanHQ::ErrorObject.new(response)
end

.exit_all!Hash{Symbol => String}

Exits all active positions and cancels all open orders for the current trading day.

This is a safety endpoint for emergency position closure. It sends a DELETE request to close all positions and cancel all pending orders in one call.

Examples:

Emergency exit all positions

response = DhanHQ::Models::Position.exit_all!
if response[:status] == "SUCCESS"
  puts "✓ All positions exited and orders cancelled"
else
  puts "✗ Failed: #{response[:message]}"
end

Returns:

  • (Hash{Symbol => String})

    Response hash containing operation result.

    • :status [String] “SUCCESS” or “ERROR”

    • :message [String] Description of the result



227
228
229
# File 'lib/DhanHQ/models/position.rb', line 227

def exit_all!
  resource.exit_all
end

.resourceDhanHQ::Resources::Positions

Provides a shared instance of the Positions resource.

Returns:



52
53
54
# File 'lib/DhanHQ/models/position.rb', line 52

def resource
  @resource ||= DhanHQ::Resources::Positions.new
end