DhanHQ 2.3.0 → 2.5.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/CHANGELOG.md +50 -1
- data/CODE_REVIEW_ISSUES.md +2 -2
- data/GUIDE.md +2 -2
- data/README.md +194 -741
- data/REVIEW_SUMMARY.md +2 -2
- data/{README1.md → docs/ARCHIVE_README.md} +4 -4
- data/docs/AUTHENTICATION.md +116 -2
- data/docs/CONFIGURATION.md +109 -0
- data/docs/SUPER_ORDERS.md +284 -0
- data/docs/TESTING_GUIDE.md +8 -8
- data/docs/TROUBLESHOOTING.md +117 -0
- data/docs/WEBSOCKET_PROTOCOL.md +154 -0
- data/docs/live_order_updates.md +2 -2
- data/docs/rails_integration.md +7 -7
- data/docs/standalone_ruby_websocket_integration.md +24 -24
- data/docs/technical_analysis.md +1 -1
- data/docs/websocket_integration.md +4 -4
- data/examples/comprehensive_websocket_examples.rb +2 -2
- data/examples/instrument_finder_test.rb +2 -2
- data/examples/market_depth_example.rb +2 -2
- data/examples/market_feed_example.rb +2 -2
- data/examples/order_update_example.rb +2 -2
- data/examples/trading_fields_example.rb +2 -2
- data/lib/DhanHQ/auth/token_generator.rb +33 -0
- data/lib/DhanHQ/auth/token_manager.rb +88 -0
- data/lib/DhanHQ/auth/token_renewal.rb +25 -0
- data/lib/DhanHQ/auth.rb +91 -31
- data/lib/DhanHQ/client.rb +42 -2
- data/lib/DhanHQ/configuration.rb +2 -2
- data/lib/DhanHQ/contracts/order_contract.rb +0 -23
- data/lib/DhanHQ/contracts/trade_by_order_id_contract.rb +12 -0
- data/lib/DhanHQ/contracts/trade_contract.rb +0 -65
- data/lib/DhanHQ/contracts/trade_history_contract.rb +52 -0
- data/lib/DhanHQ/core/auth_api.rb +21 -0
- data/lib/DhanHQ/helpers/request_helper.rb +1 -1
- data/lib/DhanHQ/models/alert_order.rb +22 -0
- data/lib/DhanHQ/models/edis.rb +110 -0
- data/lib/DhanHQ/models/kill_switch.rb +22 -0
- data/lib/DhanHQ/models/margin.rb +49 -0
- data/lib/DhanHQ/models/pnl_exit.rb +130 -0
- data/lib/DhanHQ/models/position.rb +22 -0
- data/lib/DhanHQ/models/postback.rb +123 -0
- data/lib/DhanHQ/models/token_response.rb +88 -0
- data/lib/DhanHQ/resources/kill_switch.rb +8 -0
- data/lib/DhanHQ/resources/margin_calculator.rb +9 -0
- data/lib/DhanHQ/resources/pnl_exit.rb +37 -0
- data/lib/DhanHQ/resources/positions.rb +8 -0
- data/lib/DhanHQ/version.rb +1 -1
- data/lib/dhan_hq.rb +31 -81
- metadata +46 -4
- data/lib/DhanHQ/config.rb +0 -33
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module DhanHQ
|
|
4
|
+
module Models
|
|
5
|
+
##
|
|
6
|
+
# Model for managing P&L-based automatic position exit.
|
|
7
|
+
#
|
|
8
|
+
# The P&L Based Exit API allows users to configure automatic exit rules based on
|
|
9
|
+
# cumulative profit or loss thresholds. When the defined limits are breached, all
|
|
10
|
+
# applicable positions are exited automatically.
|
|
11
|
+
#
|
|
12
|
+
# @note The configured P&L based exit remains active for the current day and is
|
|
13
|
+
# reset at the end of the trading session.
|
|
14
|
+
#
|
|
15
|
+
# @example Configure P&L-based exit
|
|
16
|
+
# response = DhanHQ::Models::PnlExit.configure(
|
|
17
|
+
# profit_value: 1500.0,
|
|
18
|
+
# loss_value: 500.0,
|
|
19
|
+
# product_type: ["INTRADAY", "DELIVERY"],
|
|
20
|
+
# enable_kill_switch: true
|
|
21
|
+
# )
|
|
22
|
+
# puts response[:pnl_exit_status] # => "ACTIVE"
|
|
23
|
+
#
|
|
24
|
+
# @example Check current P&L exit configuration
|
|
25
|
+
# config = DhanHQ::Models::PnlExit.status
|
|
26
|
+
# puts "Status: #{config.pnl_exit_status}"
|
|
27
|
+
# puts "Profit threshold: ₹#{config.profit}"
|
|
28
|
+
# puts "Loss threshold: ₹#{config.loss}"
|
|
29
|
+
#
|
|
30
|
+
# @example Stop P&L-based exit
|
|
31
|
+
# response = DhanHQ::Models::PnlExit.stop
|
|
32
|
+
# puts response[:pnl_exit_status] # => "DISABLED"
|
|
33
|
+
#
|
|
34
|
+
class PnlExit < BaseModel
|
|
35
|
+
HTTP_PATH = "/v2/pnlExit"
|
|
36
|
+
|
|
37
|
+
attributes :pnl_exit_status, :profit, :loss, :segments, :enable_kill_switch
|
|
38
|
+
|
|
39
|
+
class << self
|
|
40
|
+
##
|
|
41
|
+
# Provides a shared instance of the PnlExit resource.
|
|
42
|
+
#
|
|
43
|
+
# @return [DhanHQ::Resources::PnlExit] The PnlExit resource client instance
|
|
44
|
+
def resource
|
|
45
|
+
@resource ||= DhanHQ::Resources::PnlExit.new
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
##
|
|
49
|
+
# Configure automatic P&L-based position exit.
|
|
50
|
+
#
|
|
51
|
+
# When the defined profit or loss thresholds are breached during the trading day,
|
|
52
|
+
# all applicable positions are exited automatically.
|
|
53
|
+
#
|
|
54
|
+
# @param profit_value [Float] Profit threshold that triggers exit (e.g., 1500.0)
|
|
55
|
+
# @param loss_value [Float] Loss threshold that triggers exit (e.g., 500.0)
|
|
56
|
+
# @param product_type [Array<String>] Product types to apply. e.g., ["INTRADAY", "DELIVERY"]
|
|
57
|
+
# @param enable_kill_switch [Boolean] Whether to activate kill switch after exit
|
|
58
|
+
#
|
|
59
|
+
# @return [Hash{Symbol => String}] Response hash containing:
|
|
60
|
+
# - **:pnl_exit_status** [String] "ACTIVE" on success
|
|
61
|
+
# - **:message** [String] Confirmation message
|
|
62
|
+
#
|
|
63
|
+
# @example Configure with kill switch
|
|
64
|
+
# DhanHQ::Models::PnlExit.configure(
|
|
65
|
+
# profit_value: 2000.0,
|
|
66
|
+
# loss_value: 1000.0,
|
|
67
|
+
# product_type: ["INTRADAY"],
|
|
68
|
+
# enable_kill_switch: true
|
|
69
|
+
# )
|
|
70
|
+
#
|
|
71
|
+
def configure(profit_value:, loss_value:, product_type:, enable_kill_switch: false)
|
|
72
|
+
params = {
|
|
73
|
+
profitValue: profit_value.to_s,
|
|
74
|
+
lossValue: loss_value.to_s,
|
|
75
|
+
productType: product_type,
|
|
76
|
+
enableKillSwitch: enable_kill_switch
|
|
77
|
+
}
|
|
78
|
+
resource.configure(params)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
##
|
|
82
|
+
# Stop/disable the active P&L-based exit configuration.
|
|
83
|
+
#
|
|
84
|
+
# @return [Hash{Symbol => String}] Response hash containing:
|
|
85
|
+
# - **:pnl_exit_status** [String] "DISABLED"
|
|
86
|
+
# - **:message** [String] Confirmation message
|
|
87
|
+
#
|
|
88
|
+
# @example Disable P&L exit
|
|
89
|
+
# response = DhanHQ::Models::PnlExit.stop
|
|
90
|
+
# puts response[:pnl_exit_status] # => "DISABLED"
|
|
91
|
+
#
|
|
92
|
+
def stop
|
|
93
|
+
resource.stop
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
##
|
|
97
|
+
# Fetch the currently active P&L-based exit configuration.
|
|
98
|
+
#
|
|
99
|
+
# @return [PnlExit] PnlExit object with current configuration.
|
|
100
|
+
# - **:pnl_exit_status** [String] "ACTIVE" or "DISABLED"
|
|
101
|
+
# - **:profit** [String] Configured profit threshold
|
|
102
|
+
# - **:loss** [String] Configured loss threshold
|
|
103
|
+
# - **:segments** [Array<String>] Active product types
|
|
104
|
+
# - **:enable_kill_switch** [Boolean] Whether kill switch is enabled
|
|
105
|
+
#
|
|
106
|
+
# @example Check configuration
|
|
107
|
+
# config = DhanHQ::Models::PnlExit.status
|
|
108
|
+
# if config.pnl_exit_status == "ACTIVE"
|
|
109
|
+
# puts "P&L exit active: profit=₹#{config.profit}, loss=₹#{config.loss}"
|
|
110
|
+
# end
|
|
111
|
+
#
|
|
112
|
+
def status
|
|
113
|
+
response = resource.status
|
|
114
|
+
return nil unless response.is_a?(Hash)
|
|
115
|
+
|
|
116
|
+
new(response, skip_validation: true)
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
##
|
|
121
|
+
# No validation contract needed — server-side validation handles it.
|
|
122
|
+
#
|
|
123
|
+
# @return [nil]
|
|
124
|
+
# @api private
|
|
125
|
+
def validation_contract
|
|
126
|
+
nil
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
@@ -205,6 +205,28 @@ module DhanHQ
|
|
|
205
205
|
response = resource.convert(formatted_params)
|
|
206
206
|
success_response?(response) ? response : DhanHQ::ErrorObject.new(response)
|
|
207
207
|
end
|
|
208
|
+
|
|
209
|
+
##
|
|
210
|
+
# Exits all active positions and cancels all open orders for the current trading day.
|
|
211
|
+
#
|
|
212
|
+
# This is a safety endpoint for emergency position closure. It sends a DELETE request
|
|
213
|
+
# to close all positions and cancel all pending orders in one call.
|
|
214
|
+
#
|
|
215
|
+
# @return [Hash{Symbol => String}] Response hash containing operation result.
|
|
216
|
+
# - **:status** [String] "SUCCESS" or "ERROR"
|
|
217
|
+
# - **:message** [String] Description of the result
|
|
218
|
+
#
|
|
219
|
+
# @example Emergency exit all positions
|
|
220
|
+
# response = DhanHQ::Models::Position.exit_all!
|
|
221
|
+
# if response[:status] == "SUCCESS"
|
|
222
|
+
# puts "✓ All positions exited and orders cancelled"
|
|
223
|
+
# else
|
|
224
|
+
# puts "✗ Failed: #{response[:message]}"
|
|
225
|
+
# end
|
|
226
|
+
#
|
|
227
|
+
def exit_all!
|
|
228
|
+
resource.exit_all
|
|
229
|
+
end
|
|
208
230
|
end
|
|
209
231
|
end
|
|
210
232
|
end
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module DhanHQ
|
|
4
|
+
module Models
|
|
5
|
+
##
|
|
6
|
+
# Utility model for parsing Dhan postback (webhook) payloads.
|
|
7
|
+
#
|
|
8
|
+
# Postback is a webhook mechanism where Dhan pushes order status updates to your
|
|
9
|
+
# configured URL. This model provides a convenient way to parse the incoming JSON
|
|
10
|
+
# payload into a typed, attribute-accessible object.
|
|
11
|
+
#
|
|
12
|
+
# @note Postback URL is configured in the Dhan web console when generating an access
|
|
13
|
+
# token. It will NOT work with localhost or 127.0.0.1.
|
|
14
|
+
#
|
|
15
|
+
# @example Parse postback payload in a Rails controller
|
|
16
|
+
# class DhanWebhooksController < ApplicationController
|
|
17
|
+
# skip_before_action :verify_authenticity_token
|
|
18
|
+
#
|
|
19
|
+
# def create
|
|
20
|
+
# postback = DhanHQ::Models::Postback.parse(request.body.read)
|
|
21
|
+
# case postback.order_status
|
|
22
|
+
# when "TRADED"
|
|
23
|
+
# handle_fill(postback)
|
|
24
|
+
# when "REJECTED"
|
|
25
|
+
# handle_rejection(postback)
|
|
26
|
+
# end
|
|
27
|
+
# head :ok
|
|
28
|
+
# end
|
|
29
|
+
# end
|
|
30
|
+
#
|
|
31
|
+
# @example Parse postback payload from a hash
|
|
32
|
+
# postback = DhanHQ::Models::Postback.parse(params)
|
|
33
|
+
# puts "Order #{postback.order_id} is now #{postback.order_status}"
|
|
34
|
+
# puts "Filled: #{postback.filled_qty}/#{postback.quantity}"
|
|
35
|
+
#
|
|
36
|
+
class Postback < BaseModel
|
|
37
|
+
HTTP_PATH = nil # No API endpoint — postback is pushed to the user
|
|
38
|
+
|
|
39
|
+
attributes :dhan_client_id, :order_id, :correlation_id, :order_status,
|
|
40
|
+
:transaction_type, :exchange_segment, :product_type, :order_type,
|
|
41
|
+
:validity, :trading_symbol, :security_id, :quantity,
|
|
42
|
+
:disclosed_quantity, :price, :trigger_price, :after_market_order,
|
|
43
|
+
:bo_profit_value, :bo_stop_loss_value, :leg_name,
|
|
44
|
+
:create_time, :update_time, :exchange_time,
|
|
45
|
+
:drv_expiry_date, :drv_option_type, :drv_strike_price,
|
|
46
|
+
:oms_error_code, :oms_error_description, :filled_qty, :algo_id
|
|
47
|
+
|
|
48
|
+
class << self
|
|
49
|
+
##
|
|
50
|
+
# Parse a postback webhook payload into a Postback model instance.
|
|
51
|
+
#
|
|
52
|
+
# Accepts either a JSON string (from request body) or a Hash (from parsed params).
|
|
53
|
+
# Keys are normalized to snake_case automatically.
|
|
54
|
+
#
|
|
55
|
+
# @param payload [String, Hash] Raw JSON string or Hash from the webhook
|
|
56
|
+
#
|
|
57
|
+
# @return [Postback] Parsed Postback object with typed attributes
|
|
58
|
+
#
|
|
59
|
+
# @example From raw JSON string
|
|
60
|
+
# postback = DhanHQ::Models::Postback.parse('{"orderId":"123","orderStatus":"TRADED"}')
|
|
61
|
+
# puts postback.order_status # => "TRADED"
|
|
62
|
+
#
|
|
63
|
+
# @example From a hash
|
|
64
|
+
# postback = DhanHQ::Models::Postback.parse(order_id: "123", order_status: "TRADED")
|
|
65
|
+
# puts postback.order_id # => "123"
|
|
66
|
+
#
|
|
67
|
+
def parse(payload)
|
|
68
|
+
data = case payload
|
|
69
|
+
when String
|
|
70
|
+
JSON.parse(payload)
|
|
71
|
+
when Hash
|
|
72
|
+
payload
|
|
73
|
+
else
|
|
74
|
+
raise ArgumentError, "Expected String or Hash, got #{payload.class}"
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
new(data, skip_validation: true)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
##
|
|
82
|
+
# Whether the order has been fully traded.
|
|
83
|
+
#
|
|
84
|
+
# @return [Boolean]
|
|
85
|
+
def traded?
|
|
86
|
+
order_status == "TRADED"
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
##
|
|
90
|
+
# Whether the order was rejected.
|
|
91
|
+
#
|
|
92
|
+
# @return [Boolean]
|
|
93
|
+
def rejected?
|
|
94
|
+
order_status == "REJECTED"
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
##
|
|
98
|
+
# Whether the order is still pending.
|
|
99
|
+
#
|
|
100
|
+
# @return [Boolean]
|
|
101
|
+
def pending?
|
|
102
|
+
order_status == "PENDING"
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
##
|
|
106
|
+
# Whether the order was cancelled.
|
|
107
|
+
#
|
|
108
|
+
# @return [Boolean]
|
|
109
|
+
def cancelled?
|
|
110
|
+
order_status == "CANCELLED"
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
##
|
|
114
|
+
# No validation contract — postback payloads are parsed as-is.
|
|
115
|
+
#
|
|
116
|
+
# @return [nil]
|
|
117
|
+
# @api private
|
|
118
|
+
def validation_contract
|
|
119
|
+
nil
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "time"
|
|
4
|
+
|
|
5
|
+
module DhanHQ
|
|
6
|
+
module Models
|
|
7
|
+
# Represents a Dhan API token response with expiry tracking and validation.
|
|
8
|
+
#
|
|
9
|
+
# TokenResponse wraps the response from Dhan's token generation and renewal
|
|
10
|
+
# endpoints, providing convenient methods for checking token validity and
|
|
11
|
+
# determining when refresh is needed.
|
|
12
|
+
#
|
|
13
|
+
# @example From token generation
|
|
14
|
+
# response = Auth.generate_access_token(
|
|
15
|
+
# dhan_client_id: "123",
|
|
16
|
+
# pin: "1234",
|
|
17
|
+
# totp: "654321"
|
|
18
|
+
# )
|
|
19
|
+
# token = TokenResponse.new(response)
|
|
20
|
+
# token.expired? # => false
|
|
21
|
+
# token.expires_in # => 86400 (seconds)
|
|
22
|
+
# token.needs_refresh? # => false
|
|
23
|
+
#
|
|
24
|
+
# @example Checking token status
|
|
25
|
+
# if token.needs_refresh?(buffer_seconds: 600)
|
|
26
|
+
# # Refresh token 10 minutes before expiry
|
|
27
|
+
# new_token = Auth.renew_token(...)
|
|
28
|
+
# end
|
|
29
|
+
#
|
|
30
|
+
# @attr_reader [String] client_id Dhan client ID
|
|
31
|
+
# @attr_reader [String] client_name Dhan client name
|
|
32
|
+
# @attr_reader [String] ucc Unique client code
|
|
33
|
+
# @attr_reader [Boolean] power_of_attorney POA status
|
|
34
|
+
# @attr_reader [String] access_token The authentication token
|
|
35
|
+
# @attr_reader [Time] expiry_time Token expiration timestamp
|
|
36
|
+
class TokenResponse
|
|
37
|
+
attr_reader :client_id,
|
|
38
|
+
:client_name,
|
|
39
|
+
:ucc,
|
|
40
|
+
:power_of_attorney,
|
|
41
|
+
:access_token,
|
|
42
|
+
:expiry_time
|
|
43
|
+
|
|
44
|
+
def initialize(data)
|
|
45
|
+
data = normalize_keys(data)
|
|
46
|
+
|
|
47
|
+
@client_id = data["dhanClientId"]
|
|
48
|
+
@client_name = data["dhanClientName"]
|
|
49
|
+
@ucc = data["dhanClientUcc"]
|
|
50
|
+
@power_of_attorney = data["givenPowerOfAttorney"]
|
|
51
|
+
@access_token = data["accessToken"]
|
|
52
|
+
@expiry_time = parse_time(data["expiryTime"])
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def expired?
|
|
56
|
+
return true unless expiry_time
|
|
57
|
+
|
|
58
|
+
Time.now >= expiry_time
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def expires_in
|
|
62
|
+
return 0 unless expiry_time
|
|
63
|
+
|
|
64
|
+
expiry_time - Time.now
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def needs_refresh?(buffer_seconds: 300)
|
|
68
|
+
return true unless expiry_time
|
|
69
|
+
|
|
70
|
+
Time.now >= (expiry_time - buffer_seconds)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
private
|
|
74
|
+
|
|
75
|
+
def normalize_keys(data)
|
|
76
|
+
return {} unless data.is_a?(Hash)
|
|
77
|
+
|
|
78
|
+
data.transform_keys(&:to_s)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def parse_time(value)
|
|
82
|
+
return nil if value.nil? || value.to_s.strip.empty?
|
|
83
|
+
|
|
84
|
+
Time.parse(value.to_s)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -16,6 +16,14 @@ module DhanHQ
|
|
|
16
16
|
def update(params)
|
|
17
17
|
post("", params: params)
|
|
18
18
|
end
|
|
19
|
+
|
|
20
|
+
##
|
|
21
|
+
# Fetches the current kill switch status.
|
|
22
|
+
#
|
|
23
|
+
# @return [Hash] API response containing dhan_client_id and kill_switch_status.
|
|
24
|
+
def status
|
|
25
|
+
get("")
|
|
26
|
+
end
|
|
19
27
|
end
|
|
20
28
|
end
|
|
21
29
|
end
|
|
@@ -17,6 +17,15 @@ module DhanHQ
|
|
|
17
17
|
def calculate(params)
|
|
18
18
|
post("", params: params)
|
|
19
19
|
end
|
|
20
|
+
|
|
21
|
+
##
|
|
22
|
+
# Calculate margin requirements for multiple scripts in one request.
|
|
23
|
+
#
|
|
24
|
+
# @param params [Hash] Request parameters including scripList, includePosition, includeOrder.
|
|
25
|
+
# @return [Hash] API response containing combined margin details with hedge benefit.
|
|
26
|
+
def calculate_multi(params)
|
|
27
|
+
post("/multi", params: params)
|
|
28
|
+
end
|
|
20
29
|
end
|
|
21
30
|
end
|
|
22
31
|
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module DhanHQ
|
|
4
|
+
module Resources
|
|
5
|
+
# Resource for P&L Based Exit endpoints per https://dhanhq.co/docs/v2/traders-control/
|
|
6
|
+
# POST /v2/pnlExit — configure, DELETE /v2/pnlExit — stop, GET /v2/pnlExit — status.
|
|
7
|
+
class PnlExit < BaseAPI
|
|
8
|
+
API_TYPE = :order_api
|
|
9
|
+
HTTP_PATH = "/v2/pnlExit"
|
|
10
|
+
|
|
11
|
+
##
|
|
12
|
+
# Configure automatic P&L-based position exit.
|
|
13
|
+
#
|
|
14
|
+
# @param params [Hash] Request body with profitValue, lossValue, productType, enableKillSwitch.
|
|
15
|
+
# @return [Hash] API response containing pnlExitStatus and message.
|
|
16
|
+
def configure(params)
|
|
17
|
+
post("", params: params)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
##
|
|
21
|
+
# Stop/disable the active P&L-based exit configuration.
|
|
22
|
+
#
|
|
23
|
+
# @return [Hash] API response containing pnlExitStatus and message.
|
|
24
|
+
def stop
|
|
25
|
+
delete("")
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
##
|
|
29
|
+
# Fetch the currently active P&L-based exit configuration.
|
|
30
|
+
#
|
|
31
|
+
# @return [Hash] API response containing pnlExitStatus, profit, loss, segments, enable_kill_switch.
|
|
32
|
+
def status
|
|
33
|
+
get("")
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -24,6 +24,14 @@ module DhanHQ
|
|
|
24
24
|
def convert(params)
|
|
25
25
|
post("/convert", params: params)
|
|
26
26
|
end
|
|
27
|
+
|
|
28
|
+
##
|
|
29
|
+
# Exit all active positions and cancel all open orders.
|
|
30
|
+
#
|
|
31
|
+
# @return [Hash] API response containing status and message.
|
|
32
|
+
def exit_all
|
|
33
|
+
delete("")
|
|
34
|
+
end
|
|
27
35
|
end
|
|
28
36
|
end
|
|
29
37
|
end
|
data/lib/DhanHQ/version.rb
CHANGED
data/lib/dhan_hq.rb
CHANGED
|
@@ -1,96 +1,46 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "
|
|
3
|
+
require "json"
|
|
4
4
|
require "logger"
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
require "zeitwerk"
|
|
6
|
+
require "dotenv/load"
|
|
7
|
+
# Minimal eager requires for backward-compatible constants.
|
|
8
|
+
# These are widely referenced (e.g. `DhanHQ::BaseAPI`) and should not depend on
|
|
9
|
+
# the autoloader being fully configured.
|
|
7
10
|
require_relative "DhanHQ/helpers/api_helper"
|
|
8
11
|
require_relative "DhanHQ/helpers/attribute_helper"
|
|
9
12
|
require_relative "DhanHQ/helpers/validation_helper"
|
|
10
13
|
require_relative "DhanHQ/helpers/request_helper"
|
|
11
14
|
require_relative "DhanHQ/helpers/response_helper"
|
|
12
|
-
require_relative "DhanHQ/json_loader"
|
|
13
|
-
|
|
14
15
|
require_relative "DhanHQ/core/base_api"
|
|
15
|
-
require_relative "DhanHQ/core/base_resource"
|
|
16
16
|
require_relative "DhanHQ/core/base_model"
|
|
17
|
-
require_relative "DhanHQ/core/
|
|
18
|
-
|
|
19
|
-
require_relative "DhanHQ/version"
|
|
20
|
-
require_relative "DhanHQ/errors"
|
|
21
|
-
require_relative "DhanHQ/error_object"
|
|
22
|
-
|
|
23
|
-
require_relative "DhanHQ/client"
|
|
24
|
-
require_relative "DhanHQ/configuration"
|
|
25
|
-
require_relative "DhanHQ/rate_limiter"
|
|
26
|
-
require_relative "DhanHQ/auth"
|
|
27
|
-
|
|
28
|
-
# Contracts
|
|
29
|
-
require_relative "DhanHQ/contracts/base_contract"
|
|
30
|
-
require_relative "DhanHQ/contracts/historical_data_contract"
|
|
31
|
-
require_relative "DhanHQ/contracts/margin_calculator_contract"
|
|
32
|
-
require_relative "DhanHQ/contracts/position_conversion_contract"
|
|
33
|
-
require_relative "DhanHQ/contracts/slice_order_contract"
|
|
34
|
-
require_relative "DhanHQ/contracts/trade_contract"
|
|
35
|
-
require_relative "DhanHQ/contracts/expired_options_data_contract"
|
|
36
|
-
require_relative "DhanHQ/contracts/alert_order_contract"
|
|
37
|
-
|
|
38
|
-
# Resources
|
|
39
|
-
require_relative "DhanHQ/resources/option_chain"
|
|
40
|
-
require_relative "DhanHQ/resources/orders"
|
|
41
|
-
require_relative "DhanHQ/resources/forever_orders"
|
|
42
|
-
require_relative "DhanHQ/resources/super_orders"
|
|
43
|
-
require_relative "DhanHQ/resources/funds"
|
|
44
|
-
require_relative "DhanHQ/resources/holdings"
|
|
45
|
-
require_relative "DhanHQ/resources/positions"
|
|
46
|
-
require_relative "DhanHQ/resources/statements"
|
|
47
|
-
require_relative "DhanHQ/resources/trades"
|
|
48
|
-
require_relative "DhanHQ/resources/historical_data"
|
|
49
|
-
require_relative "DhanHQ/resources/margin_calculator"
|
|
50
|
-
require_relative "DhanHQ/resources/market_feed"
|
|
51
|
-
require_relative "DhanHQ/resources/instruments"
|
|
52
|
-
require_relative "DhanHQ/resources/alert_orders"
|
|
53
|
-
require_relative "DhanHQ/resources/edis"
|
|
54
|
-
require_relative "DhanHQ/resources/ip_setup"
|
|
55
|
-
require_relative "DhanHQ/resources/kill_switch"
|
|
56
|
-
require_relative "DhanHQ/resources/trader_control"
|
|
57
|
-
require_relative "DhanHQ/resources/profile"
|
|
58
|
-
require_relative "DhanHQ/resources/expired_options_data"
|
|
59
|
-
|
|
60
|
-
# Models
|
|
61
|
-
require_relative "DhanHQ/models/alert_order"
|
|
62
|
-
require_relative "DhanHQ/models/order"
|
|
63
|
-
require_relative "DhanHQ/models/funds"
|
|
64
|
-
require_relative "DhanHQ/models/option_chain"
|
|
65
|
-
require_relative "DhanHQ/models/forever_order"
|
|
66
|
-
require_relative "DhanHQ/models/super_order"
|
|
67
|
-
require_relative "DhanHQ/models/historical_data"
|
|
68
|
-
require_relative "DhanHQ/models/market_feed"
|
|
69
|
-
require_relative "DhanHQ/models/instrument"
|
|
70
|
-
require_relative "DhanHQ/models/position"
|
|
71
|
-
require_relative "DhanHQ/models/holding"
|
|
72
|
-
require_relative "DhanHQ/models/ledger_entry"
|
|
73
|
-
require_relative "DhanHQ/models/trade"
|
|
74
|
-
require_relative "DhanHQ/models/margin"
|
|
75
|
-
require_relative "DhanHQ/models/kill_switch"
|
|
76
|
-
require_relative "DhanHQ/models/profile"
|
|
77
|
-
require_relative "DhanHQ/models/order_update"
|
|
78
|
-
require_relative "DhanHQ/models/expired_options_data"
|
|
79
|
-
|
|
80
|
-
require_relative "DhanHQ/constants"
|
|
81
|
-
require_relative "DhanHQ/ws"
|
|
82
|
-
require_relative "DhanHQ/ws/singleton_lock"
|
|
83
|
-
require_relative "ta"
|
|
84
|
-
require_relative "dhanhq/analysis/multi_timeframe_analyzer"
|
|
85
|
-
require_relative "dhanhq/analysis/helpers/bias_aggregator"
|
|
86
|
-
require_relative "dhanhq/analysis/helpers/moneyness_helper"
|
|
87
|
-
require_relative "dhanhq/contracts/options_buying_advisor_contract"
|
|
88
|
-
require_relative "dhanhq/analysis/options_buying_advisor"
|
|
17
|
+
require_relative "DhanHQ/core/base_resource"
|
|
89
18
|
|
|
90
19
|
# The top-level module for the DhanHQ client library.
|
|
91
20
|
#
|
|
92
21
|
# Provides configuration management for setting credentials and API-related settings.
|
|
93
22
|
module DhanHQ
|
|
23
|
+
LOADER = Zeitwerk::Loader.new
|
|
24
|
+
LOADER.tag = "dhanhq"
|
|
25
|
+
LOADER.inflector.inflect(
|
|
26
|
+
"api_helper" => "APIHelper",
|
|
27
|
+
"auth_api" => "AuthAPI",
|
|
28
|
+
"base_api" => "BaseAPI",
|
|
29
|
+
"ip_setup" => "IPSetup",
|
|
30
|
+
"json_loader" => "JSONLoader",
|
|
31
|
+
"ws" => "WS"
|
|
32
|
+
)
|
|
33
|
+
LOADER.push_dir(File.join(__dir__, "DhanHQ"), namespace: self)
|
|
34
|
+
LOADER.push_dir(File.join(__dir__, "dhanhq"), namespace: self)
|
|
35
|
+
LOADER.collapse(File.join(__dir__, "DhanHQ", "core"))
|
|
36
|
+
LOADER.collapse(File.join(__dir__, "DhanHQ", "helpers"))
|
|
37
|
+
LOADER.collapse(File.join(__dir__, "dhanhq", "analysis", "helpers"))
|
|
38
|
+
LOADER.ignore(
|
|
39
|
+
File.join(__dir__, "DhanHQ", "errors.rb"),
|
|
40
|
+
File.join(__dir__, "DhanHQ", "version.rb")
|
|
41
|
+
)
|
|
42
|
+
LOADER.setup
|
|
43
|
+
|
|
94
44
|
class Error < StandardError; end
|
|
95
45
|
|
|
96
46
|
class << self
|
|
@@ -131,7 +81,7 @@ module DhanHQ
|
|
|
131
81
|
|
|
132
82
|
# Configures the DhanHQ client using environment variables.
|
|
133
83
|
#
|
|
134
|
-
# When credentials are injected via `
|
|
84
|
+
# When credentials are injected via `DHAN_ACCESS_TOKEN` and `DHAN_CLIENT_ID` this helper
|
|
135
85
|
# can be used to initialise a configuration without a block.
|
|
136
86
|
#
|
|
137
87
|
# @example
|
|
@@ -140,8 +90,8 @@ module DhanHQ
|
|
|
140
90
|
# @return [void]
|
|
141
91
|
def configure_with_env
|
|
142
92
|
self.configuration ||= Configuration.new
|
|
143
|
-
configuration.access_token = ENV.fetch("
|
|
144
|
-
configuration.client_id = ENV.fetch("
|
|
93
|
+
configuration.access_token = ENV.fetch("DHAN_ACCESS_TOKEN", nil)
|
|
94
|
+
configuration.client_id = ENV.fetch("DHAN_CLIENT_ID", nil)
|
|
145
95
|
configuration.base_url = ENV.fetch("DHAN_BASE_URL", BASE_URL)
|
|
146
96
|
configuration.ws_version = ENV.fetch("DHAN_WS_VERSION", configuration.ws_version || 2).to_i
|
|
147
97
|
configuration.ws_order_url = ENV.fetch("DHAN_WS_ORDER_URL", configuration.ws_order_url)
|