ollama-client 0.2.2 → 0.2.3
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 +8 -0
- data/README.md +7 -1
- data/docs/CLOUD.md +29 -0
- data/docs/CONSOLE_IMPROVEMENTS.md +256 -0
- data/docs/README.md +37 -0
- data/docs/SCHEMA_FIXES.md +147 -0
- data/docs/TEST_UPDATES.md +107 -0
- data/examples/README.md +92 -0
- data/examples/advanced_complex_schemas.rb +6 -3
- data/examples/advanced_multi_step_agent.rb +2 -1
- data/examples/chat_console.rb +12 -3
- data/examples/complete_workflow.rb +14 -4
- data/examples/dhan_console.rb +103 -8
- data/examples/dhanhq/agents/technical_analysis_agent.rb +6 -1
- data/examples/dhanhq/schemas/agent_schemas.rb +2 -2
- data/examples/dhanhq_agent.rb +23 -13
- data/examples/dhanhq_tools.rb +311 -246
- data/examples/multi_step_agent_with_external_data.rb +368 -0
- data/{test_dhanhq_tool_calling.rb → examples/test_dhanhq_tool_calling.rb} +99 -6
- data/lib/ollama/agent/executor.rb +30 -30
- data/lib/ollama/client.rb +73 -80
- data/lib/ollama/dto.rb +7 -7
- data/lib/ollama/options.rb +17 -9
- data/lib/ollama/response.rb +4 -6
- data/lib/ollama/tool/function/parameters.rb +1 -0
- data/lib/ollama/version.rb +1 -1
- metadata +14 -7
- /data/{FEATURES_ADDED.md → docs/FEATURES_ADDED.md} +0 -0
- /data/{HANDLERS_ANALYSIS.md → docs/HANDLERS_ANALYSIS.md} +0 -0
- /data/{PRODUCTION_FIXES.md → docs/PRODUCTION_FIXES.md} +0 -0
- /data/{TESTING.md → docs/TESTING.md} +0 -0
- /data/{test_tool_calling.rb → examples/test_tool_calling.rb} +0 -0
data/examples/README.md
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Examples
|
|
2
|
+
|
|
3
|
+
This directory contains working examples demonstrating various features of the ollama-client gem.
|
|
4
|
+
|
|
5
|
+
## Quick Start Examples
|
|
6
|
+
|
|
7
|
+
### Basic Tool Calling
|
|
8
|
+
- **[test_tool_calling.rb](test_tool_calling.rb)** - Simple tool calling demo with weather tool
|
|
9
|
+
- **[tool_calling_pattern.rb](tool_calling_pattern.rb)** - Recommended patterns for tool calling
|
|
10
|
+
- **[tool_calling_direct.rb](tool_calling_direct.rb)** - Direct tool calling without Executor
|
|
11
|
+
|
|
12
|
+
### DhanHQ Market Data
|
|
13
|
+
- **[test_dhanhq_tool_calling.rb](test_dhanhq_tool_calling.rb)** - DhanHQ tools with updated intraday & indicators
|
|
14
|
+
- **[dhanhq_tools.rb](dhanhq_tools.rb)** - DhanHQ API wrapper tools
|
|
15
|
+
- **[dhan_console.rb](dhan_console.rb)** - Interactive DhanHQ console with planning
|
|
16
|
+
|
|
17
|
+
### Multi-Step Agents
|
|
18
|
+
- **[multi_step_agent_e2e.rb](multi_step_agent_e2e.rb)** - End-to-end multi-step agent example
|
|
19
|
+
- **[multi_step_agent_with_external_data.rb](multi_step_agent_with_external_data.rb)** - Agent with external data integration
|
|
20
|
+
|
|
21
|
+
### Structured Data
|
|
22
|
+
- **[structured_outputs_chat.rb](structured_outputs_chat.rb)** - Structured outputs with schemas
|
|
23
|
+
- **[structured_tools.rb](structured_tools.rb)** - Structured tool definitions
|
|
24
|
+
- **[tool_dto_example.rb](tool_dto_example.rb)** - Using DTOs for tool definitions
|
|
25
|
+
|
|
26
|
+
### Advanced Features
|
|
27
|
+
- **[advanced_multi_step_agent.rb](advanced_multi_step_agent.rb)** - Complex multi-step workflows
|
|
28
|
+
- **[advanced_error_handling.rb](advanced_error_handling.rb)** - Error handling patterns
|
|
29
|
+
- **[advanced_edge_cases.rb](advanced_edge_cases.rb)** - Edge case handling
|
|
30
|
+
- **[advanced_complex_schemas.rb](advanced_complex_schemas.rb)** - Complex schema definitions
|
|
31
|
+
- **[advanced_performance_testing.rb](advanced_performance_testing.rb)** - Performance testing
|
|
32
|
+
|
|
33
|
+
### Interactive Consoles
|
|
34
|
+
- **[chat_console.rb](chat_console.rb)** - Simple chat console with streaming
|
|
35
|
+
- **[dhan_console.rb](dhan_console.rb)** - DhanHQ market data console with formatted tool results
|
|
36
|
+
|
|
37
|
+
### Complete Workflows
|
|
38
|
+
- **[complete_workflow.rb](complete_workflow.rb)** - Complete agent workflow example
|
|
39
|
+
|
|
40
|
+
## DhanHQ Examples
|
|
41
|
+
|
|
42
|
+
The `dhanhq/` subdirectory contains more specialized DhanHQ examples:
|
|
43
|
+
- Technical analysis agents
|
|
44
|
+
- Market scanners (intraday options, swing trading)
|
|
45
|
+
- Pattern recognition and trend analysis
|
|
46
|
+
- Multi-agent orchestration
|
|
47
|
+
|
|
48
|
+
See [dhanhq/README.md](dhanhq/README.md) for details.
|
|
49
|
+
|
|
50
|
+
## Running Examples
|
|
51
|
+
|
|
52
|
+
Most examples are standalone and can be run directly:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# Basic tool calling
|
|
56
|
+
ruby examples/test_tool_calling.rb
|
|
57
|
+
|
|
58
|
+
# DhanHQ with intraday data
|
|
59
|
+
ruby examples/test_dhanhq_tool_calling.rb
|
|
60
|
+
|
|
61
|
+
# Interactive console
|
|
62
|
+
ruby examples/chat_console.rb
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Requirements
|
|
66
|
+
|
|
67
|
+
Some examples require additional setup:
|
|
68
|
+
|
|
69
|
+
**DhanHQ Examples:**
|
|
70
|
+
- Set `DHANHQ_CLIENT_ID` and `DHANHQ_ACCESS_TOKEN` environment variables
|
|
71
|
+
- Or create `.env` file with credentials
|
|
72
|
+
|
|
73
|
+
**Ollama:**
|
|
74
|
+
- Ollama server running (default: `http://localhost:11434`)
|
|
75
|
+
- Set `OLLAMA_BASE_URL` if using a different URL
|
|
76
|
+
- Set `OLLAMA_MODEL` if not using default model
|
|
77
|
+
|
|
78
|
+
## Learning Path
|
|
79
|
+
|
|
80
|
+
1. **Start here:** `test_tool_calling.rb` - Learn basic tool calling
|
|
81
|
+
2. **Structured data:** `structured_outputs_chat.rb` - Schema-based outputs
|
|
82
|
+
3. **Multi-step:** `multi_step_agent_e2e.rb` - Complex agent workflows
|
|
83
|
+
4. **Market data:** `test_dhanhq_tool_calling.rb` - Real-world API integration
|
|
84
|
+
5. **Interactive:** `dhan_console.rb` - Full-featured console with planning
|
|
85
|
+
|
|
86
|
+
## Contributing
|
|
87
|
+
|
|
88
|
+
When adding new examples:
|
|
89
|
+
- Include clear comments explaining what the example demonstrates
|
|
90
|
+
- Add `#!/usr/bin/env ruby` shebang at the top
|
|
91
|
+
- Use `frozen_string_literal: true`
|
|
92
|
+
- Update this README with a description
|
|
@@ -35,7 +35,8 @@ class FinancialAnalyzer
|
|
|
35
35
|
"profit_margin" => {
|
|
36
36
|
"type" => "number",
|
|
37
37
|
"minimum" => 0,
|
|
38
|
-
"maximum" => 100
|
|
38
|
+
"maximum" => 100,
|
|
39
|
+
"description" => "Profit margin as percentage (0 to 100)"
|
|
39
40
|
},
|
|
40
41
|
"growth_rate" => {
|
|
41
42
|
"type" => "number"
|
|
@@ -121,7 +122,8 @@ class CodeReviewer
|
|
|
121
122
|
"overall_score" => {
|
|
122
123
|
"type" => "integer",
|
|
123
124
|
"minimum" => 0,
|
|
124
|
-
"maximum" => 100
|
|
125
|
+
"maximum" => 100,
|
|
126
|
+
"description" => "Overall quality score (0 to 100)"
|
|
125
127
|
},
|
|
126
128
|
"issues" => {
|
|
127
129
|
"type" => "array",
|
|
@@ -262,7 +264,8 @@ class ResearchAnalyzer
|
|
|
262
264
|
"reproducibility_score" => {
|
|
263
265
|
"type" => "number",
|
|
264
266
|
"minimum" => 0,
|
|
265
|
-
"maximum" => 1
|
|
267
|
+
"maximum" => 1,
|
|
268
|
+
"description" => "Reproducibility score (0.0 to 1.0, where 1.0 means fully reproducible)"
|
|
266
269
|
}
|
|
267
270
|
}
|
|
268
271
|
}
|
data/examples/chat_console.rb
CHANGED
|
@@ -39,8 +39,8 @@ MAX_HISTORY = 200
|
|
|
39
39
|
COLOR_RESET = "\e[0m"
|
|
40
40
|
COLOR_USER = "\e[32m"
|
|
41
41
|
COLOR_LLM = "\e[36m"
|
|
42
|
-
USER_PROMPT = "#{COLOR_USER}you>#{COLOR_RESET} "
|
|
43
|
-
LLM_PROMPT = "#{COLOR_LLM}llm>#{COLOR_RESET} "
|
|
42
|
+
USER_PROMPT = "#{COLOR_USER}you>#{COLOR_RESET} ".freeze
|
|
43
|
+
LLM_PROMPT = "#{COLOR_LLM}llm>#{COLOR_RESET} ".freeze
|
|
44
44
|
|
|
45
45
|
def build_reader
|
|
46
46
|
TTY::Reader.new
|
|
@@ -86,7 +86,10 @@ end
|
|
|
86
86
|
|
|
87
87
|
def chat_response(client, messages, config)
|
|
88
88
|
content = +""
|
|
89
|
-
|
|
89
|
+
prompt_printed = false
|
|
90
|
+
|
|
91
|
+
print "#{COLOR_LLM}...#{COLOR_RESET}"
|
|
92
|
+
$stdout.flush
|
|
90
93
|
|
|
91
94
|
client.chat_raw(
|
|
92
95
|
messages: messages,
|
|
@@ -97,8 +100,14 @@ def chat_response(client, messages, config)
|
|
|
97
100
|
token = chunk.dig("message", "content").to_s
|
|
98
101
|
next if token.empty?
|
|
99
102
|
|
|
103
|
+
unless prompt_printed
|
|
104
|
+
print "\r#{LLM_PROMPT}"
|
|
105
|
+
prompt_printed = true
|
|
106
|
+
end
|
|
107
|
+
|
|
100
108
|
content << token
|
|
101
109
|
print token
|
|
110
|
+
$stdout.flush
|
|
102
111
|
end
|
|
103
112
|
|
|
104
113
|
puts
|
|
@@ -30,7 +30,7 @@ class TaskPlanner
|
|
|
30
30
|
"type" => "number",
|
|
31
31
|
"minimum" => 0,
|
|
32
32
|
"maximum" => 1,
|
|
33
|
-
"description" => "Confidence in this decision"
|
|
33
|
+
"description" => "Confidence in this decision (0.0 to 1.0, where 1.0 is 100% confident)"
|
|
34
34
|
},
|
|
35
35
|
"next_step" => {
|
|
36
36
|
"type" => "string",
|
|
@@ -49,8 +49,13 @@ class TaskPlanner
|
|
|
49
49
|
puts "Context: #{context}\n\n"
|
|
50
50
|
|
|
51
51
|
begin
|
|
52
|
+
prompt = "Given this context: #{context}\n\n" \
|
|
53
|
+
"Decide the next action to take.\n\n" \
|
|
54
|
+
"IMPORTANT: Use decimal values for confidence " \
|
|
55
|
+
"(e.g., 0.95 for 95% confident, 0.80 for 80% confident, 1.0 for 100% confident)."
|
|
56
|
+
|
|
52
57
|
result = @client.generate(
|
|
53
|
-
prompt:
|
|
58
|
+
prompt: prompt,
|
|
54
59
|
schema: @task_schema
|
|
55
60
|
)
|
|
56
61
|
|
|
@@ -132,7 +137,8 @@ class DataAnalyzer
|
|
|
132
137
|
"confidence" => {
|
|
133
138
|
"type" => "number",
|
|
134
139
|
"minimum" => 0,
|
|
135
|
-
"maximum" => 1
|
|
140
|
+
"maximum" => 1,
|
|
141
|
+
"description" => "Confidence level (0.0 to 1.0, where 1.0 is 100% confident)"
|
|
136
142
|
},
|
|
137
143
|
"key_points" => {
|
|
138
144
|
"type" => "array",
|
|
@@ -157,8 +163,12 @@ class DataAnalyzer
|
|
|
157
163
|
puts "Data: #{data}\n\n"
|
|
158
164
|
|
|
159
165
|
begin
|
|
166
|
+
prompt = "Analyze this data and provide insights: #{data}\n\n" \
|
|
167
|
+
"IMPORTANT: Express confidence as a decimal between 0.0 and 1.0 " \
|
|
168
|
+
"(e.g., 0.85 for 85% confidence, not 85)."
|
|
169
|
+
|
|
160
170
|
result = @client.generate(
|
|
161
|
-
prompt:
|
|
171
|
+
prompt: prompt,
|
|
162
172
|
schema: @analysis_schema
|
|
163
173
|
)
|
|
164
174
|
|
data/examples/dhan_console.rb
CHANGED
|
@@ -42,8 +42,8 @@ MAX_HISTORY = 200
|
|
|
42
42
|
COLOR_RESET = "\e[0m"
|
|
43
43
|
COLOR_USER = "\e[32m"
|
|
44
44
|
COLOR_LLM = "\e[36m"
|
|
45
|
-
USER_PROMPT = "#{COLOR_USER}you>#{COLOR_RESET} "
|
|
46
|
-
LLM_PROMPT = "#{COLOR_LLM}llm>#{COLOR_RESET} "
|
|
45
|
+
USER_PROMPT = "#{COLOR_USER}you>#{COLOR_RESET} ".freeze
|
|
46
|
+
LLM_PROMPT = "#{COLOR_LLM}llm>#{COLOR_RESET} ".freeze
|
|
47
47
|
|
|
48
48
|
def build_reader
|
|
49
49
|
TTY::Reader.new
|
|
@@ -497,7 +497,7 @@ def build_tools
|
|
|
497
497
|
"get_historical_data" => lambda do |exchange_segment:, from_date:, to_date:, symbol: nil, security_id: nil,
|
|
498
498
|
interval: nil, expiry_code: nil, calculate_indicators: false|
|
|
499
499
|
# Convert security_id to integer if provided (LLM may pass it as string)
|
|
500
|
-
normalized_security_id = security_id
|
|
500
|
+
normalized_security_id = security_id&.to_i
|
|
501
501
|
DhanHQDataTools.get_historical_data(**compact_kwargs(exchange_segment: exchange_segment,
|
|
502
502
|
symbol: symbol,
|
|
503
503
|
security_id: normalized_security_id,
|
|
@@ -509,14 +509,14 @@ def build_tools
|
|
|
509
509
|
end,
|
|
510
510
|
"get_expiry_list" => lambda do |exchange_segment:, symbol: nil, security_id: nil|
|
|
511
511
|
# Convert security_id to integer if provided (LLM may pass it as string)
|
|
512
|
-
normalized_security_id = security_id
|
|
512
|
+
normalized_security_id = security_id&.to_i
|
|
513
513
|
DhanHQDataTools.get_expiry_list(**compact_kwargs(exchange_segment: exchange_segment,
|
|
514
514
|
symbol: symbol,
|
|
515
515
|
security_id: normalized_security_id))
|
|
516
516
|
end,
|
|
517
517
|
"get_option_chain" => lambda do |exchange_segment:, symbol: nil, security_id: nil, expiry: nil, strikes_count: 5|
|
|
518
518
|
# Convert security_id to integer if provided (LLM may pass it as string)
|
|
519
|
-
normalized_security_id = security_id
|
|
519
|
+
normalized_security_id = security_id&.to_i
|
|
520
520
|
# Default to 5 strikes (2 ITM, ATM, 2 OTM) - good balance for analysis
|
|
521
521
|
normalized_strikes_count = strikes_count.to_i
|
|
522
522
|
normalized_strikes_count = 5 if normalized_strikes_count < 1 # Minimum 1 (ATM)
|
|
@@ -555,16 +555,18 @@ def tool_messages(messages)
|
|
|
555
555
|
end
|
|
556
556
|
|
|
557
557
|
def print_tool_results(messages)
|
|
558
|
-
puts "Tool Results:"
|
|
559
558
|
tool_messages(messages).each do |message|
|
|
560
559
|
print_tool_message(message)
|
|
561
560
|
end
|
|
561
|
+
puts # blank line after tool results
|
|
562
562
|
end
|
|
563
563
|
|
|
564
564
|
def print_tool_message(message)
|
|
565
565
|
tool_name = message[:name] || "unknown_tool"
|
|
566
|
-
|
|
567
|
-
|
|
566
|
+
content = parse_tool_content(message[:content])
|
|
567
|
+
|
|
568
|
+
puts "\n#{COLOR_LLM}🔧 Tool Called:#{COLOR_RESET} #{tool_name}"
|
|
569
|
+
print_formatted_result(tool_name, content)
|
|
568
570
|
end
|
|
569
571
|
|
|
570
572
|
def format_tool_content(content)
|
|
@@ -582,6 +584,99 @@ rescue JSON::ParserError
|
|
|
582
584
|
content
|
|
583
585
|
end
|
|
584
586
|
|
|
587
|
+
def print_formatted_result(tool_name, content)
|
|
588
|
+
return puts content if content.is_a?(String)
|
|
589
|
+
|
|
590
|
+
result = content["result"] || content
|
|
591
|
+
|
|
592
|
+
case tool_name
|
|
593
|
+
when "get_live_ltp"
|
|
594
|
+
print_ltp_result(result)
|
|
595
|
+
when "get_market_quote"
|
|
596
|
+
print_quote_result(result)
|
|
597
|
+
when "get_historical_data"
|
|
598
|
+
print_historical_result(result, content)
|
|
599
|
+
when "get_option_chain"
|
|
600
|
+
print_option_chain_result(result)
|
|
601
|
+
when "get_expiry_list"
|
|
602
|
+
print_expiry_list_result(result)
|
|
603
|
+
when "find_instrument"
|
|
604
|
+
print_instrument_result(result)
|
|
605
|
+
else
|
|
606
|
+
puts " #{COLOR_LLM}→#{COLOR_RESET} #{JSON.pretty_generate(content)}"
|
|
607
|
+
end
|
|
608
|
+
end
|
|
609
|
+
|
|
610
|
+
def print_ltp_result(result)
|
|
611
|
+
symbol = result["symbol"] || "Unknown"
|
|
612
|
+
ltp = result["ltp"] || result.dig("ltp_data", "last_price")
|
|
613
|
+
exchange = result["exchange_segment"]
|
|
614
|
+
|
|
615
|
+
puts " #{COLOR_LLM}→#{COLOR_RESET} #{symbol} (#{exchange})"
|
|
616
|
+
puts " #{COLOR_LLM}→#{COLOR_RESET} Last Price: ₹#{ltp}"
|
|
617
|
+
end
|
|
618
|
+
|
|
619
|
+
def print_quote_result(result)
|
|
620
|
+
symbol = result["symbol"] || "Unknown"
|
|
621
|
+
quote = result["quote"] || {}
|
|
622
|
+
ohlc = quote["ohlc"] || {}
|
|
623
|
+
|
|
624
|
+
puts " #{COLOR_LLM}→#{COLOR_RESET} #{symbol}"
|
|
625
|
+
puts " #{COLOR_LLM}→#{COLOR_RESET} LTP: ₹#{quote['last_price']}"
|
|
626
|
+
puts " #{COLOR_LLM}→#{COLOR_RESET} OHLC: O:#{ohlc['open']} H:#{ohlc['high']} L:#{ohlc['low']} C:#{ohlc['close']}"
|
|
627
|
+
puts " #{COLOR_LLM}→#{COLOR_RESET} Volume: #{quote['volume']}" if quote["volume"]&.positive?
|
|
628
|
+
end
|
|
629
|
+
|
|
630
|
+
def print_historical_result(result, content)
|
|
631
|
+
if result.is_a?(Hash) && result.key?("indicators")
|
|
632
|
+
print_indicator_result(result)
|
|
633
|
+
elsif result.is_a?(Hash)
|
|
634
|
+
data_points = result["data"]&.size || 0
|
|
635
|
+
interval = content.dig("params", "interval")
|
|
636
|
+
puts " #{COLOR_LLM}→#{COLOR_RESET} Historical data: #{data_points} records"
|
|
637
|
+
puts " #{COLOR_LLM}→#{COLOR_RESET} Interval: #{interval}" if interval
|
|
638
|
+
elsif result.is_a?(Array)
|
|
639
|
+
puts " #{COLOR_LLM}→#{COLOR_RESET} #{result.size} data points"
|
|
640
|
+
end
|
|
641
|
+
end
|
|
642
|
+
|
|
643
|
+
def print_indicator_result(result)
|
|
644
|
+
indicators = result["indicators"]
|
|
645
|
+
puts " #{COLOR_LLM}→#{COLOR_RESET} Technical Indicators:"
|
|
646
|
+
puts " #{COLOR_LLM}→#{COLOR_RESET} Current Price: ₹#{indicators['current_price']}"
|
|
647
|
+
puts " #{COLOR_LLM}→#{COLOR_RESET} RSI(14): #{indicators['rsi']&.round(2)}"
|
|
648
|
+
puts " #{COLOR_LLM}→#{COLOR_RESET} MACD: #{indicators.dig('macd', 'macd')&.round(2)}"
|
|
649
|
+
puts " #{COLOR_LLM}→#{COLOR_RESET} SMA(20): ₹#{indicators['sma_20']&.round(2)}"
|
|
650
|
+
puts " #{COLOR_LLM}→#{COLOR_RESET} SMA(50): ₹#{indicators['sma_50']&.round(2)}"
|
|
651
|
+
end
|
|
652
|
+
|
|
653
|
+
def print_option_chain_result(result)
|
|
654
|
+
oc = result.dig("data", "oc") || {}
|
|
655
|
+
last_price = result.dig("data", "last_price")
|
|
656
|
+
strikes = oc.keys.size
|
|
657
|
+
|
|
658
|
+
puts " #{COLOR_LLM}→#{COLOR_RESET} Spot: ₹#{last_price}"
|
|
659
|
+
puts " #{COLOR_LLM}→#{COLOR_RESET} Strikes: #{strikes}"
|
|
660
|
+
puts " #{COLOR_LLM}→#{COLOR_RESET} (Filtered: ATM/OTM/ITM with both CE & PE)"
|
|
661
|
+
end
|
|
662
|
+
|
|
663
|
+
def print_expiry_list_result(result)
|
|
664
|
+
expiries = result["expiries"] || []
|
|
665
|
+
puts " #{COLOR_LLM}→#{COLOR_RESET} Available expiries: #{expiries.size}"
|
|
666
|
+
puts " #{COLOR_LLM}→#{COLOR_RESET} Next expiry: #{expiries.first}" if expiries.any?
|
|
667
|
+
puts " #{COLOR_LLM}→#{COLOR_RESET} Expiries: #{expiries[0..4].join(', ')}#{'...' if expiries.size > 5}"
|
|
668
|
+
end
|
|
669
|
+
|
|
670
|
+
def print_instrument_result(result)
|
|
671
|
+
symbol = result["symbol"]
|
|
672
|
+
security_id = result["security_id"]
|
|
673
|
+
exchange = result["exchange_segment"]
|
|
674
|
+
|
|
675
|
+
puts " #{COLOR_LLM}→#{COLOR_RESET} Found: #{symbol}"
|
|
676
|
+
puts " #{COLOR_LLM}→#{COLOR_RESET} Security ID: #{security_id}"
|
|
677
|
+
puts " #{COLOR_LLM}→#{COLOR_RESET} Exchange: #{exchange}"
|
|
678
|
+
end
|
|
679
|
+
|
|
585
680
|
def show_llm_summary?
|
|
586
681
|
ENV["SHOW_LLM_SUMMARY"] == "true"
|
|
587
682
|
end
|
|
@@ -236,7 +236,12 @@ module DhanHQ
|
|
|
236
236
|
"stop_loss" => { "type" => "number" },
|
|
237
237
|
"target_price" => { "type" => "number" },
|
|
238
238
|
"risk_reward_ratio" => { "type" => "number" },
|
|
239
|
-
"confidence" => {
|
|
239
|
+
"confidence" => {
|
|
240
|
+
"type" => "number",
|
|
241
|
+
"minimum" => 0,
|
|
242
|
+
"maximum" => 1,
|
|
243
|
+
"description" => "Confidence (0.0 to 1.0)"
|
|
244
|
+
},
|
|
240
245
|
"reasoning" => { "type" => "string" },
|
|
241
246
|
"timeframe" => { "type" => "string" }
|
|
242
247
|
}
|
|
@@ -21,7 +21,7 @@ module DhanHQ
|
|
|
21
21
|
"type" => "number",
|
|
22
22
|
"minimum" => 0,
|
|
23
23
|
"maximum" => 1,
|
|
24
|
-
"description" => "Confidence in this decision"
|
|
24
|
+
"description" => "Confidence in this decision (0.0 to 1.0, where 1.0 is 100% confident)"
|
|
25
25
|
},
|
|
26
26
|
"parameters" => {
|
|
27
27
|
"type" => "object",
|
|
@@ -47,7 +47,7 @@ module DhanHQ
|
|
|
47
47
|
"type" => "number",
|
|
48
48
|
"minimum" => 0,
|
|
49
49
|
"maximum" => 1,
|
|
50
|
-
"description" => "Confidence in this decision"
|
|
50
|
+
"description" => "Confidence in this decision (0.0 to 1.0, where 1.0 is 100% confident)"
|
|
51
51
|
},
|
|
52
52
|
"parameters" => {
|
|
53
53
|
"type" => "object",
|
data/examples/dhanhq_agent.rb
CHANGED
|
@@ -76,7 +76,7 @@ class DataAgent
|
|
|
76
76
|
"type" => "number",
|
|
77
77
|
"minimum" => 0,
|
|
78
78
|
"maximum" => 1,
|
|
79
|
-
"description" => "Confidence in this decision"
|
|
79
|
+
"description" => "Confidence in this decision (0.0 to 1.0, where 1.0 is 100% confident)"
|
|
80
80
|
},
|
|
81
81
|
"parameters" => {
|
|
82
82
|
"type" => "object",
|
|
@@ -304,7 +304,7 @@ class TradingAgent
|
|
|
304
304
|
"type" => "number",
|
|
305
305
|
"minimum" => 0,
|
|
306
306
|
"maximum" => 1,
|
|
307
|
-
"description" => "Confidence in this decision"
|
|
307
|
+
"description" => "Confidence in this decision (0.0 to 1.0, where 1.0 is 100% confident)"
|
|
308
308
|
},
|
|
309
309
|
"parameters" => {
|
|
310
310
|
"type" => "object",
|
|
@@ -662,16 +662,26 @@ if __FILE__ == $PROGRAM_NAME
|
|
|
662
662
|
puts " ⚠️ RELIANCE data error: #{e.message}"
|
|
663
663
|
end
|
|
664
664
|
|
|
665
|
-
# NOTE: Positions and holdings are not part of the 6 Data APIs
|
|
665
|
+
# NOTE: Positions and holdings are not part of the 6 Data APIs, but available via DhanHQ gem
|
|
666
666
|
begin
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
667
|
+
positions_list = DhanHQ::Models::Position.all
|
|
668
|
+
positions_data = positions_list.map do |pos|
|
|
669
|
+
{
|
|
670
|
+
trading_symbol: pos.trading_symbol,
|
|
671
|
+
quantity: pos.net_qty,
|
|
672
|
+
average_price: pos.buy_avg,
|
|
673
|
+
exchange_segment: pos.exchange_segment,
|
|
674
|
+
security_id: pos.security_id,
|
|
675
|
+
pnl: pos.realized_profit
|
|
676
|
+
}
|
|
677
|
+
end
|
|
678
|
+
market_data[:positions] = positions_data
|
|
679
|
+
puts " ✅ Positions: #{positions_data.length} active"
|
|
680
|
+
|
|
681
|
+
if positions_data.any?
|
|
682
|
+
positions_data.each do |pos|
|
|
683
|
+
puts " - #{pos[:trading_symbol]}: Qty #{pos[:quantity]} @ ₹#{pos[:average_price]}"
|
|
684
|
+
end
|
|
675
685
|
end
|
|
676
686
|
rescue StandardError => e
|
|
677
687
|
puts " ⚠️ Positions error: #{e.message}"
|
|
@@ -852,8 +862,8 @@ if __FILE__ == $PROGRAM_NAME
|
|
|
852
862
|
begin
|
|
853
863
|
# NOTE: Options symbols may need different format
|
|
854
864
|
# Try with NIFTY which typically has options
|
|
855
|
-
# First, get the list of available expiries
|
|
856
|
-
expiry_list_result = DhanHQDataTools.
|
|
865
|
+
# First, get the list of available expiries using get_expiry_list
|
|
866
|
+
expiry_list_result = DhanHQDataTools.get_expiry_list(
|
|
857
867
|
symbol: "NIFTY", # NIFTY typically has options, RELIANCE might not
|
|
858
868
|
exchange_segment: "IDX_I"
|
|
859
869
|
)
|