Class: DhanHQ::Models::Trade

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

Overview

Model for retrieving trade execution details.

The Trade Book API lets you retrieve an array of all trades executed in a day. You can also fetch trade details for a specific order ID, which is useful during partial trades or Bracket/Cover Orders. Additionally, you can retrieve detailed trade history for all orders within a particular time frame.

Examples:

Fetch all trades for today

trades = DhanHQ::Models::Trade.today
trades.each do |trade|
  puts "#{trade.trading_symbol}: #{trade.traded_quantity} @ ₹#{trade.traded_price}"
  puts "Total Value: ₹#{trade.total_value}, Charges: ₹#{trade.total_charges}"
end

Fetch trades for a specific order

trade = DhanHQ::Models::Trade.find_by_order_id("112111182045")
if trade
  puts "Traded: #{trade.traded_quantity} @ ₹#{trade.traded_price}"
end

Fetch historical trades

trades = DhanHQ::Models::Trade.history(
  from_date: "2022-12-01",
  to_date: "2022-12-31",
  page: 0
)
total_value = trades.sum(&:total_value)
puts "Total traded value: ₹#{total_value}"

Constant Summary collapse

HTTP_PATH =
"/v2/trades"

Constants included from ResponseHelper

ResponseHelper::STATUS_ERROR_FALLBACK

Instance Attribute Summary

Attributes inherited from BaseModel

#attributes, #errors

Class Method Summary collapse

Instance 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, #deep_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

.find_by_order_id(order_id) ⇒ Trade?

Retrieves trade details for a specific order ID (current day).

Fetches all trades generated for a particular order ID. This is especially useful during partial trades or Bracket/Cover Orders where traders may get confused reading trades from the tradebook. The response includes all trades generated for the specified order ID.

Examples:

Fetch trade for an order

trade = DhanHQ::Models::Trade.find_by_order_id("112111182045")
if trade
  puts "Order: #{trade.order_id}"
  puts "Traded: #{trade.traded_quantity} @ ₹#{trade.traded_price}"
  puts "Symbol: #{trade.trading_symbol}"
  puts "Time: #{trade.exchange_time}"
end

Parameters:

  • order_id (String)

    Order-specific identification generated by Dhan

Returns:

  • (Trade, nil)

    Trade object with trade details if found, nil otherwise. Response structure is the same as today.

Raises:



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/DhanHQ/models/trade.rb', line 150

def find_by_order_id(order_id)
  # Validate input
  contract = DhanHQ::Contracts::TradeByOrderIdContract.new
  validation_result = contract.call(order_id: order_id)

  unless validation_result.success?
    raise DhanHQ::ValidationError, "Invalid order_id: #{validation_result.errors.to_h}"
  end

  response = resource.find(order_id)
  return nil unless response.is_a?(Hash) || (response.is_a?(Array) && response.any?)

  data = response.is_a?(Array) ? response.first : response
  new(data, skip_validation: true)
end

.history(from_date:, to_date:, page: 0) ⇒ Array<Trade> Also known as: all

Retrieves detailed trade history for all orders within a specified time frame.

Fetches paginated trade history data with comprehensive charge breakdowns. The response includes detailed information about SEBI tax, STT, brokerage charges, service tax, exchange transaction charges, and stamp duty for each trade.

Examples:

Fetch historical trades for a month

trades = DhanHQ::Models::Trade.history(
  from_date: "2022-12-01",
  to_date: "2022-12-31",
  page: 0
)
puts "Total trades: #{trades.count}"

Calculate total charges for historical period

trades = DhanHQ::Models::Trade.history(
  from_date: "2022-12-01",
  to_date: "2022-12-31"
)
total_charges = trades.sum(&:total_charges)
total_brokerage = trades.sum { |t| t.brokerage_charges.to_f }
puts "Total Charges: ₹#{total_charges}"
puts "Total Brokerage: ₹#{total_brokerage}"

Paginate through historical trades

page = 0
loop do
  trades = DhanHQ::Models::Trade.history(
    from_date: "2022-12-01",
    to_date: "2022-12-31",
    page: page
  )
  break if trades.empty?

  puts "Page #{page}: #{trades.count} trades"
  page += 1
end

Parameters:

  • from_date (String)

    (required) Start date in "YYYY-MM-DD" format

  • to_date (String)

    (required) End date in "YYYY-MM-DD" format

  • page (Integer) (defaults to: 0)

    (default: 0) Page number for paginated results. Pass 0 for first page

Returns:

  • (Array<Trade>)

    Array of historical Trade objects. Returns empty array if no trades found. Each Trade object contains all fields from today plus additional charge details:

    • :custom_symbol [String] Trading Symbol as per Dhan
    • :isin [String] Universal standard ID for each scrip (International Securities Identification Number)
    • :instrument [String] Type of Instrument. "EQUITY" or "DERIVATIVES"
    • :sebi_tax [String] SEBI Turnover Charges
    • :stt [String] Securities Transactions Tax
    • :brokerage_charges [String] Brokerage charges by Dhan
    • :service_tax [String] Applicable Service Tax
    • :exchange_transaction_charges [String] Exchange Transaction Charge
    • :stamp_duty [String] Stamp Duty Charges

Raises:



222
223
224
225
226
227
228
229
230
231
232
233
234
# File 'lib/DhanHQ/models/trade.rb', line 222

def history(from_date:, to_date:, page: 0)
  validate_history_params(from_date, to_date, page)

  response = statements_resource.trade_history(
    from_date: from_date,
    to_date: to_date,
    page: page
  )

  return [] unless response.is_a?(Array)

  response.map { |trade_data| new(trade_data, skip_validation: true) }
end

.resourceDhanHQ::Resources::Trades

Provides a shared instance of the Trades resource for current day tradebook APIs.

Returns:



65
66
67
# File 'lib/DhanHQ/models/trade.rb', line 65

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

.statements_resourceDhanHQ::Resources::Statements

Provides a shared instance of the Statements resource for historical trade data.

Returns:



73
74
75
# File 'lib/DhanHQ/models/trade.rb', line 73

def statements_resource
  @statements_resource ||= DhanHQ::Resources::Statements.new
end

.todayArray<Trade>

Retrieves all trades executed during the current trading day.

Fetches an array of all trades executed in the day. This is useful for tracking daily execution activity and analyzing trade performance.

Examples:

Fetch and analyze today's trades

trades = DhanHQ::Models::Trade.today
buy_trades = trades.select(&:buy?)
sell_trades = trades.select(&:sell?)
puts "Buy trades: #{buy_trades.count}, Sell trades: #{sell_trades.count}"
total_value = trades.sum(&:total_value)
puts "Total traded value: ₹#{total_value}"

Calculate P&L for today

trades = DhanHQ::Models::Trade.today
buy_value = trades.select(&:buy?).sum(&:total_value)
sell_value = trades.select(&:sell?).sum(&:total_value)
total_charges = trades.sum(&:total_charges)
pnl = sell_value - buy_value - total_charges
puts "P&L: ₹#{pnl}"

Returns:

  • (Array<Trade>)

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

    • :dhan_client_id [String] User-specific identification generated by Dhan
    • :order_id [String] Order-specific identification generated by Dhan
    • :exchange_order_id [String] Order-specific identification generated by exchange
    • :exchange_trade_id [String] Trade-specific identification generated by exchange
    • :transaction_type [String] The trading side of transaction. "BUY" or "SELL"
    • :exchange_segment [String] Exchange segment of instrument
    • :product_type [String] Product type. Valid values: "CNC", "INTRADAY", "MARGIN", "MTF", "CO", "BO"
    • :order_type [String] Order type. Valid values: "LIMIT", "MARKET", "STOP_LOSS", "STOP_LOSS_MARKET"
    • :trading_symbol [String] Trading symbol of the instrument
    • :security_id [String] Exchange standard ID for each scrip
    • :traded_quantity [Integer] Number of shares executed
    • :traded_price [Float] Price at which trade is executed
    • :create_time [String] Time at which the order is created
    • :update_time [String] Time at which the last activity happened
    • :exchange_time [String] Time at which order reached at exchange
    • :drv_expiry_date [String, nil] For F&O, expiry date of contract
    • :drv_option_type [String, nil] Type of Option. "CALL" or "PUT"
    • :drv_strike_price [Float] For Options, Strike Price


122
123
124
125
# File 'lib/DhanHQ/models/trade.rb', line 122

def today
  response = resource.all
  parse_collection_response(response)
end

Instance Method Details

#buy?Boolean

Checks if the trade is a BUY transaction.

Examples:

trade = DhanHQ::Models::Trade.today.first
if trade.buy?
  puts "This is a buy trade"
end

Returns:

  • (Boolean)

    true if transaction_type is "BUY", false otherwise



273
274
275
# File 'lib/DhanHQ/models/trade.rb', line 273

def buy?
  transaction_type == DhanHQ::Constants::TransactionType::BUY
end

#call_option?Boolean

Checks if the trade is a CALL option.

Examples:

trades = DhanHQ::Models::Trade.today
call_trades = trades.select(&:call_option?)
puts "Call option trades: #{call_trades.count}"

Returns:

  • (Boolean)

    true if drv_option_type is "CALL", false otherwise



344
345
346
# File 'lib/DhanHQ/models/trade.rb', line 344

def call_option?
  drv_option_type == DhanHQ::Constants::OptionType::CALL
end

#derivative?Boolean

Checks if the trade instrument is DERIVATIVES.

Examples:

trades = DhanHQ::Models::Trade.today
derivative_trades = trades.select(&:derivative?)
puts "Derivative trades: #{derivative_trades.count}"

Returns:

  • (Boolean)

    true if instrument is "DERIVATIVES", false otherwise



316
317
318
# File 'lib/DhanHQ/models/trade.rb', line 316

def derivative?
  instrument == "DERIVATIVES"
end

#equity?Boolean

Checks if the trade instrument is EQUITY.

Examples:

trades = DhanHQ::Models::Trade.today
equity_trades = trades.select(&:equity?)
puts "Equity trades: #{equity_trades.count}"

Returns:

  • (Boolean)

    true if instrument is "EQUITY", false otherwise



302
303
304
# File 'lib/DhanHQ/models/trade.rb', line 302

def equity?
  instrument == DhanHQ::Constants::InstrumentType::EQUITY
end

#net_valueFloat

Calculates the net trade value after deducting all charges.

Examples:

trade = DhanHQ::Models::Trade.history(
  from_date: "2022-12-01",
  to_date: "2022-12-31"
).first
puts "Gross Value: ₹#{trade.total_value}"
puts "Charges: ₹#{trade.total_charges}"
puts "Net Value: ₹#{trade.net_value}"

Returns:

  • (Float)

    Net trade value (total_value - total_charges)



415
416
417
# File 'lib/DhanHQ/models/trade.rb', line 415

def net_value
  total_value - total_charges
end

#option?Boolean

Checks if the trade is an option (CALL or PUT).

Examples:

trades = DhanHQ::Models::Trade.today
option_trades = trades.select(&:option?)
puts "Option trades: #{option_trades.count}"

Returns:

  • (Boolean)

    true if drv_option_type is "CALL" or "PUT", false otherwise



330
331
332
# File 'lib/DhanHQ/models/trade.rb', line 330

def option?
  [DhanHQ::Constants::OptionType::CALL, DhanHQ::Constants::OptionType::PUT].include?(drv_option_type)
end

#put_option?Boolean

Checks if the trade is a PUT option.

Examples:

trades = DhanHQ::Models::Trade.today
put_trades = trades.select(&:put_option?)
puts "Put option trades: #{put_trades.count}"

Returns:

  • (Boolean)

    true if drv_option_type is "PUT", false otherwise



358
359
360
# File 'lib/DhanHQ/models/trade.rb', line 358

def put_option?
  drv_option_type == DhanHQ::Constants::OptionType::PUT
end

#sell?Boolean

Checks if the trade is a SELL transaction.

Examples:

trade = DhanHQ::Models::Trade.today.first
if trade.sell?
  puts "This is a sell trade"
end

Returns:

  • (Boolean)

    true if transaction_type is "SELL", false otherwise



288
289
290
# File 'lib/DhanHQ/models/trade.rb', line 288

def sell?
  transaction_type == DhanHQ::Constants::TransactionType::SELL
end

#to_promptObject

Returns a concise prompt-friendly summary of the trade.



48
49
50
51
52
53
54
55
56
57
58
# File 'lib/DhanHQ/models/trade.rb', line 48

def to_prompt
  parts = [
    "#{transaction_type} #{traded_quantity}x #{trading_symbol || security_id}",
    "@ ₹#{traded_price}",
    "on #{exchange_segment}/#{product_type}"
  ]
  parts << "order=#{order_id}" if order_id
  parts << "charges=₹#{total_charges}" if respond_to?(:total_charges) && total_charges
  parts << "time=#{create_time}" if create_time
  parts.join(", ")
end

#total_chargesFloat

Calculates the total charges for the trade.

Sums all applicable charges including SEBI tax, STT, brokerage charges, service tax, exchange transaction charges, and stamp duty.

Examples:

trade = DhanHQ::Models::Trade.history(
  from_date: "2022-12-01",
  to_date: "2022-12-31"
).first
puts "Total Charges: ₹#{trade.total_charges}"
puts "Brokerage: ₹#{trade.brokerage_charges}"
puts "STT: ₹#{trade.stt}"

Returns:

  • (Float)

    Total charges amount. Returns 0 if no charges are present



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

def total_charges
  charges = [sebi_tax, stt, brokerage_charges, service_tax,
             exchange_transaction_charges, stamp_duty].compact
  charges.sum(&:to_f)
end

#total_valueFloat

Calculates the total trade value (quantity × price).

Examples:

trade = DhanHQ::Models::Trade.today.first
puts "Trade Value: ₹#{trade.total_value}"
# => Trade Value: ₹133832.0

Returns:

  • (Float)

    Total trade value. Returns 0 if traded_quantity or traded_price is missing



372
373
374
375
376
# File 'lib/DhanHQ/models/trade.rb', line 372

def total_value
  return 0 unless traded_quantity && traded_price

  traded_quantity * traded_price
end