ollama-client 0.2.5 → 0.2.7
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 +22 -0
- data/README.md +336 -91
- data/RELEASE_NOTES_v0.2.6.md +41 -0
- data/docs/AREAS_FOR_CONSIDERATION.md +325 -0
- data/docs/EXAMPLE_REORGANIZATION.md +412 -0
- data/docs/FEATURES_ADDED.md +12 -1
- data/docs/GETTING_STARTED.md +361 -0
- data/docs/INTEGRATION_TESTING.md +170 -0
- data/docs/NEXT_STEPS_SUMMARY.md +114 -0
- data/docs/PERSONAS.md +383 -0
- data/docs/QUICK_START.md +195 -0
- data/docs/TESTING.md +392 -170
- data/docs/TEST_CHECKLIST.md +450 -0
- data/examples/README.md +62 -63
- data/examples/basic_chat.rb +33 -0
- data/examples/basic_generate.rb +29 -0
- data/examples/mcp_executor.rb +39 -0
- data/examples/mcp_http_executor.rb +45 -0
- data/examples/tool_calling_parsing.rb +59 -0
- data/examples/tool_dto_example.rb +0 -0
- data/exe/ollama-client +128 -1
- data/lib/ollama/agent/planner.rb +7 -2
- data/lib/ollama/chat_session.rb +101 -0
- data/lib/ollama/client.rb +41 -35
- data/lib/ollama/config.rb +9 -4
- data/lib/ollama/document_loader.rb +1 -1
- data/lib/ollama/embeddings.rb +61 -28
- data/lib/ollama/errors.rb +1 -0
- data/lib/ollama/mcp/http_client.rb +149 -0
- data/lib/ollama/mcp/stdio_client.rb +146 -0
- data/lib/ollama/mcp/tools_bridge.rb +72 -0
- data/lib/ollama/mcp.rb +31 -0
- data/lib/ollama/options.rb +3 -1
- data/lib/ollama/personas.rb +287 -0
- data/lib/ollama/version.rb +1 -1
- data/lib/ollama_client.rb +17 -5
- metadata +22 -48
- data/examples/advanced_complex_schemas.rb +0 -366
- data/examples/advanced_edge_cases.rb +0 -241
- data/examples/advanced_error_handling.rb +0 -200
- data/examples/advanced_multi_step_agent.rb +0 -341
- data/examples/advanced_performance_testing.rb +0 -186
- data/examples/chat_console.rb +0 -143
- data/examples/complete_workflow.rb +0 -245
- data/examples/dhan_console.rb +0 -843
- data/examples/dhanhq/README.md +0 -236
- data/examples/dhanhq/agents/base_agent.rb +0 -74
- data/examples/dhanhq/agents/data_agent.rb +0 -66
- data/examples/dhanhq/agents/orchestrator_agent.rb +0 -120
- data/examples/dhanhq/agents/technical_analysis_agent.rb +0 -252
- data/examples/dhanhq/agents/trading_agent.rb +0 -81
- data/examples/dhanhq/analysis/market_structure.rb +0 -138
- data/examples/dhanhq/analysis/pattern_recognizer.rb +0 -192
- data/examples/dhanhq/analysis/trend_analyzer.rb +0 -88
- data/examples/dhanhq/builders/market_context_builder.rb +0 -67
- data/examples/dhanhq/dhanhq_agent.rb +0 -829
- data/examples/dhanhq/indicators/technical_indicators.rb +0 -158
- data/examples/dhanhq/scanners/intraday_options_scanner.rb +0 -492
- data/examples/dhanhq/scanners/swing_scanner.rb +0 -247
- data/examples/dhanhq/schemas/agent_schemas.rb +0 -61
- data/examples/dhanhq/services/base_service.rb +0 -46
- data/examples/dhanhq/services/data_service.rb +0 -118
- data/examples/dhanhq/services/trading_service.rb +0 -59
- data/examples/dhanhq/technical_analysis_agentic_runner.rb +0 -411
- data/examples/dhanhq/technical_analysis_runner.rb +0 -420
- data/examples/dhanhq/test_tool_calling.rb +0 -538
- data/examples/dhanhq/test_tool_calling_verbose.rb +0 -251
- data/examples/dhanhq/utils/instrument_helper.rb +0 -32
- data/examples/dhanhq/utils/parameter_cleaner.rb +0 -28
- data/examples/dhanhq/utils/parameter_normalizer.rb +0 -45
- data/examples/dhanhq/utils/rate_limiter.rb +0 -23
- data/examples/dhanhq/utils/trading_parameter_normalizer.rb +0 -72
- data/examples/dhanhq_agent.rb +0 -964
- data/examples/dhanhq_tools.rb +0 -1663
- data/examples/multi_step_agent_with_external_data.rb +0 -368
- data/examples/structured_outputs_chat.rb +0 -72
- data/examples/structured_tools.rb +0 -89
- data/examples/test_dhanhq_tool_calling.rb +0 -375
- data/examples/test_tool_calling.rb +0 -160
- data/examples/tool_calling_direct.rb +0 -124
- data/examples/tool_calling_pattern.rb +0 -269
- data/exe/dhan_console +0 -4
|
@@ -1,420 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
# Technical Analysis Runner - Run only technical analysis examples
|
|
5
|
-
# Usage: ruby examples/dhanhq/technical_analysis_runner.rb
|
|
6
|
-
|
|
7
|
-
require "json"
|
|
8
|
-
require "date"
|
|
9
|
-
require "dhan_hq"
|
|
10
|
-
require_relative "../../lib/ollama_client"
|
|
11
|
-
require_relative "../dhanhq_tools"
|
|
12
|
-
|
|
13
|
-
# Load all modules
|
|
14
|
-
require_relative "utils/instrument_helper"
|
|
15
|
-
require_relative "utils/rate_limiter"
|
|
16
|
-
require_relative "utils/parameter_normalizer"
|
|
17
|
-
require_relative "utils/parameter_cleaner"
|
|
18
|
-
require_relative "utils/trading_parameter_normalizer"
|
|
19
|
-
require_relative "builders/market_context_builder"
|
|
20
|
-
require_relative "schemas/agent_schemas"
|
|
21
|
-
require_relative "services/base_service"
|
|
22
|
-
require_relative "services/data_service"
|
|
23
|
-
require_relative "services/trading_service"
|
|
24
|
-
require_relative "indicators/technical_indicators"
|
|
25
|
-
require_relative "analysis/market_structure"
|
|
26
|
-
require_relative "analysis/pattern_recognizer"
|
|
27
|
-
require_relative "analysis/trend_analyzer"
|
|
28
|
-
require_relative "agents/base_agent"
|
|
29
|
-
require_relative "agents/data_agent"
|
|
30
|
-
require_relative "agents/trading_agent"
|
|
31
|
-
require_relative "agents/technical_analysis_agent"
|
|
32
|
-
require_relative "agents/orchestrator_agent"
|
|
33
|
-
require_relative "scanners/swing_scanner"
|
|
34
|
-
require_relative "scanners/intraday_options_scanner"
|
|
35
|
-
|
|
36
|
-
# Load the Agent class definition
|
|
37
|
-
module DhanHQ
|
|
38
|
-
# Main agent orchestrator
|
|
39
|
-
class Agent
|
|
40
|
-
def initialize(ollama_client: nil, trading_ollama_client: nil)
|
|
41
|
-
@ollama_client = ollama_client || Ollama::Client.new
|
|
42
|
-
@trading_ollama_client = trading_ollama_client || create_trading_client
|
|
43
|
-
@data_agent = Agents::DataAgent.new(ollama_client: @ollama_client)
|
|
44
|
-
@trading_agent = Agents::TradingAgent.new(ollama_client: @trading_ollama_client)
|
|
45
|
-
@analysis_agent = Agents::TechnicalAnalysisAgent.new(ollama_client: @ollama_client)
|
|
46
|
-
@orchestrator_agent = Agents::OrchestratorAgent.new(ollama_client: @ollama_client)
|
|
47
|
-
@swing_scanner = Scanners::SwingScanner.new
|
|
48
|
-
@options_scanner = Scanners::IntradayOptionsScanner.new
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
attr_reader :data_agent, :trading_agent, :analysis_agent, :orchestrator_agent, :swing_scanner, :options_scanner
|
|
52
|
-
|
|
53
|
-
private
|
|
54
|
-
|
|
55
|
-
def create_trading_client
|
|
56
|
-
config = Ollama::Config.new
|
|
57
|
-
config.timeout = 60
|
|
58
|
-
Ollama::Client.new(config: config)
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
# Configure DhanHQ
|
|
64
|
-
begin
|
|
65
|
-
DhanHQ.configure_with_env
|
|
66
|
-
puts "✅ DhanHQ configured"
|
|
67
|
-
rescue StandardError => e
|
|
68
|
-
puts "⚠️ DhanHQ configuration error: #{e.message}"
|
|
69
|
-
puts " Make sure CLIENT_ID and ACCESS_TOKEN are set in ENV"
|
|
70
|
-
puts " Continuing with mock data for demonstration..."
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
puts "=" * 60
|
|
74
|
-
puts "TECHNICAL ANALYSIS - LLM-POWERED ORCHESTRATION"
|
|
75
|
-
puts "=" * 60
|
|
76
|
-
puts
|
|
77
|
-
|
|
78
|
-
# Helper methods (defined before use)
|
|
79
|
-
def perform_technical_analysis(agent, symbol, exchange_segment)
|
|
80
|
-
analysis_result = agent.analysis_agent.analyze_symbol(
|
|
81
|
-
symbol: symbol,
|
|
82
|
-
exchange_segment: exchange_segment
|
|
83
|
-
)
|
|
84
|
-
|
|
85
|
-
return log_analysis_error(analysis_result) if analysis_result[:error]
|
|
86
|
-
|
|
87
|
-
analysis = analysis_result[:analysis]
|
|
88
|
-
return log_analysis_empty if analysis.nil? || analysis.empty?
|
|
89
|
-
|
|
90
|
-
log_analysis_summary(analysis)
|
|
91
|
-
rescue StandardError => e
|
|
92
|
-
puts " ❌ Error: #{e.message}"
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
def perform_swing_scan(agent, symbol, exchange_segment)
|
|
96
|
-
candidates = agent.swing_scanner.scan_symbols(
|
|
97
|
-
[symbol],
|
|
98
|
-
exchange_segment: exchange_segment,
|
|
99
|
-
min_score: 40,
|
|
100
|
-
verbose: false
|
|
101
|
-
)
|
|
102
|
-
|
|
103
|
-
if candidates.empty?
|
|
104
|
-
puts " ⚠️ No swing candidates found (score < 40)"
|
|
105
|
-
else
|
|
106
|
-
candidate = candidates.first
|
|
107
|
-
puts " ✅ Swing Candidate Found"
|
|
108
|
-
puts " 📈 Score: #{candidate[:score]}/100"
|
|
109
|
-
puts " 📊 Trend: #{candidate[:analysis][:trend][:trend]}"
|
|
110
|
-
puts " 💡 #{candidate[:recommendation] || 'Analysis complete'}"
|
|
111
|
-
end
|
|
112
|
-
rescue StandardError => e
|
|
113
|
-
puts " ❌ Error: #{e.message}"
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
def perform_options_scan(agent, symbol, exchange_segment)
|
|
117
|
-
options_setups = agent.options_scanner.scan_for_options_setups(
|
|
118
|
-
symbol,
|
|
119
|
-
exchange_segment: exchange_segment,
|
|
120
|
-
min_score: 40,
|
|
121
|
-
verbose: true
|
|
122
|
-
)
|
|
123
|
-
|
|
124
|
-
if options_setups[:error]
|
|
125
|
-
puts " ⚠️ #{options_setups[:error]}"
|
|
126
|
-
elsif options_setups[:setups] && !options_setups[:setups].empty?
|
|
127
|
-
puts " ✅ Found #{options_setups[:setups].length} options setups"
|
|
128
|
-
options_setups[:setups].first(3).each do |setup|
|
|
129
|
-
puts " 📊 #{setup[:type].to_s.upcase} @ #{setup[:strike]}: Score #{setup[:score]}/100"
|
|
130
|
-
end
|
|
131
|
-
else
|
|
132
|
-
puts " ⚠️ No options setups found (min_score: 40)"
|
|
133
|
-
puts " Try lowering min_score or check verbose output above for details"
|
|
134
|
-
end
|
|
135
|
-
rescue StandardError => e
|
|
136
|
-
puts " ❌ Error: #{e.message}"
|
|
137
|
-
puts " #{e.backtrace.first(3).join("\n ")}" if e.backtrace
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
# Initialize agent
|
|
141
|
-
agent = DhanHQ::Agent.new
|
|
142
|
-
|
|
143
|
-
# ============================================================
|
|
144
|
-
# LLM-POWERED ORCHESTRATION
|
|
145
|
-
# ============================================================
|
|
146
|
-
puts "🤔 Letting LLM decide what to analyze..."
|
|
147
|
-
puts "─" * 60
|
|
148
|
-
|
|
149
|
-
# Get market context first (can be fetched from real data)
|
|
150
|
-
market_context = ARGV[1] || "Current market: SENSEX, NIFTY and RELIANCE are active. Looking for trading opportunities."
|
|
151
|
-
|
|
152
|
-
user_query = ARGV[0] || "Analyze SENSEX and find swing trading opportunities"
|
|
153
|
-
|
|
154
|
-
puts "User Query: #{user_query}"
|
|
155
|
-
puts "Market Context: #{market_context}"
|
|
156
|
-
puts
|
|
157
|
-
|
|
158
|
-
begin
|
|
159
|
-
plan = agent.orchestrator_agent.decide_analysis_plan(
|
|
160
|
-
market_context: market_context,
|
|
161
|
-
user_query: user_query
|
|
162
|
-
)
|
|
163
|
-
|
|
164
|
-
if plan[:error]
|
|
165
|
-
puts " ⚠️ Error creating plan: #{plan[:error]}"
|
|
166
|
-
puts " Falling back to default analysis..."
|
|
167
|
-
plan = {
|
|
168
|
-
"analysis_plan" => [
|
|
169
|
-
{ "symbol" => "RELIANCE", "exchange_segment" => "NSE_EQ", "analysis_type" => "technical_analysis",
|
|
170
|
-
"priority" => 1 },
|
|
171
|
-
{ "symbol" => "TCS", "exchange_segment" => "NSE_EQ", "analysis_type" => "swing_scan", "priority" => 2 },
|
|
172
|
-
{ "symbol" => "NIFTY", "exchange_segment" => "IDX_I", "analysis_type" => "options_scan", "priority" => 3 }
|
|
173
|
-
],
|
|
174
|
-
"reasoning" => "Default fallback plan"
|
|
175
|
-
}
|
|
176
|
-
end
|
|
177
|
-
|
|
178
|
-
puts "📋 Analysis Plan:"
|
|
179
|
-
puts " Reasoning: #{plan['reasoning'] || 'N/A'}"
|
|
180
|
-
puts " Tasks: #{plan['analysis_plan']&.length || 0} analysis tasks"
|
|
181
|
-
puts
|
|
182
|
-
|
|
183
|
-
# Sort by priority
|
|
184
|
-
tasks = (plan["analysis_plan"] || []).sort_by { |t| t["priority"] || 999 }
|
|
185
|
-
|
|
186
|
-
tasks.each_with_index do |task, idx|
|
|
187
|
-
symbol = task["symbol"]
|
|
188
|
-
exchange_segment = task["exchange_segment"]
|
|
189
|
-
analysis_type = task["analysis_type"]
|
|
190
|
-
|
|
191
|
-
puts "=" * 60
|
|
192
|
-
puts "Task #{idx + 1}: #{analysis_type} for #{symbol} (#{exchange_segment})"
|
|
193
|
-
puts "─" * 60
|
|
194
|
-
|
|
195
|
-
if analysis_type == "all"
|
|
196
|
-
perform_technical_analysis(agent, symbol, exchange_segment)
|
|
197
|
-
perform_swing_scan(agent, symbol, exchange_segment)
|
|
198
|
-
perform_options_scan(agent, symbol, exchange_segment)
|
|
199
|
-
else
|
|
200
|
-
case analysis_type
|
|
201
|
-
when "technical_analysis"
|
|
202
|
-
perform_technical_analysis(agent, symbol, exchange_segment)
|
|
203
|
-
when "swing_scan"
|
|
204
|
-
perform_swing_scan(agent, symbol, exchange_segment)
|
|
205
|
-
when "options_scan"
|
|
206
|
-
perform_options_scan(agent, symbol, exchange_segment)
|
|
207
|
-
end
|
|
208
|
-
end
|
|
209
|
-
|
|
210
|
-
puts
|
|
211
|
-
end
|
|
212
|
-
rescue StandardError => e
|
|
213
|
-
puts " ❌ Error: #{e.message}"
|
|
214
|
-
puts " #{e.backtrace.first(3).join("\n ")}" if e.backtrace
|
|
215
|
-
end
|
|
216
|
-
|
|
217
|
-
def log_analysis_error(analysis_result)
|
|
218
|
-
puts " ⚠️ Error: #{analysis_result[:error]}"
|
|
219
|
-
end
|
|
220
|
-
|
|
221
|
-
def log_analysis_empty
|
|
222
|
-
puts " ⚠️ Error: Analysis returned empty result"
|
|
223
|
-
end
|
|
224
|
-
|
|
225
|
-
def log_analysis_summary(analysis)
|
|
226
|
-
puts " ✅ Analysis Complete"
|
|
227
|
-
puts trend_summary_text(analysis)
|
|
228
|
-
puts rsi_summary_text(analysis)
|
|
229
|
-
puts macd_summary_text(analysis)
|
|
230
|
-
puts current_price_text(analysis)
|
|
231
|
-
puts patterns_summary_text(analysis)
|
|
232
|
-
puts structure_break_text(analysis)
|
|
233
|
-
end
|
|
234
|
-
|
|
235
|
-
def trend_summary_text(analysis)
|
|
236
|
-
trend = analysis[:trend] || {}
|
|
237
|
-
trend_name = trend[:trend] || "N/A"
|
|
238
|
-
strength = trend[:strength] || 0
|
|
239
|
-
" 📊 Trend: #{trend_name} (#{strength}% strength)"
|
|
240
|
-
end
|
|
241
|
-
|
|
242
|
-
def rsi_summary_text(analysis)
|
|
243
|
-
rsi = analysis[:indicators]&.dig(:rsi)
|
|
244
|
-
rsi_text = rsi ? rsi.round(2) : "N/A"
|
|
245
|
-
" 📊 RSI: #{rsi_text}"
|
|
246
|
-
end
|
|
247
|
-
|
|
248
|
-
def macd_summary_text(analysis)
|
|
249
|
-
macd = analysis[:indicators]&.dig(:macd)
|
|
250
|
-
macd_text = macd ? macd.round(2) : "N/A"
|
|
251
|
-
" 📊 MACD: #{macd_text}"
|
|
252
|
-
end
|
|
253
|
-
|
|
254
|
-
def current_price_text(analysis)
|
|
255
|
-
current_price = analysis[:current_price] || "N/A"
|
|
256
|
-
" 📊 Current Price: #{current_price}"
|
|
257
|
-
end
|
|
258
|
-
|
|
259
|
-
def patterns_summary_text(analysis)
|
|
260
|
-
candlestick_patterns = analysis[:patterns]&.dig(:candlestick) || []
|
|
261
|
-
" 📊 Patterns: #{candlestick_patterns.length} patterns"
|
|
262
|
-
end
|
|
263
|
-
|
|
264
|
-
def structure_break_text(analysis)
|
|
265
|
-
broken = analysis[:structure_break]&.dig(:broken)
|
|
266
|
-
" 📊 Structure Break: #{broken ? 'Yes' : 'No'}"
|
|
267
|
-
end
|
|
268
|
-
|
|
269
|
-
def format_score_breakdown(details)
|
|
270
|
-
"Trend=#{details[:trend]}, RSI=#{details[:rsi]}, MACD=#{details[:macd]}, " \
|
|
271
|
-
"Structure=#{details[:structure]}, Patterns=#{details[:patterns]}"
|
|
272
|
-
end
|
|
273
|
-
|
|
274
|
-
def format_option_setup_details(setup)
|
|
275
|
-
iv = setup[:iv]&.round(2) || "N/A"
|
|
276
|
-
oi = setup[:oi] || "N/A"
|
|
277
|
-
volume = setup[:volume] || "N/A"
|
|
278
|
-
"IV: #{iv}% | OI: #{oi} | Volume: #{volume}"
|
|
279
|
-
end
|
|
280
|
-
|
|
281
|
-
# Uncomment below to also run manual examples for comparison
|
|
282
|
-
if ENV["SHOW_MANUAL_EXAMPLES"] == "true"
|
|
283
|
-
puts "=" * 60
|
|
284
|
-
puts "TECHNICAL ANALYSIS EXAMPLES (Manual - for comparison)"
|
|
285
|
-
puts "=" * 60
|
|
286
|
-
puts
|
|
287
|
-
|
|
288
|
-
# ============================================================
|
|
289
|
-
# MANUAL EXAMPLES (for comparison)
|
|
290
|
-
# ============================================================
|
|
291
|
-
puts "Example 1: Technical Analysis for RELIANCE"
|
|
292
|
-
puts "─" * 60
|
|
293
|
-
|
|
294
|
-
begin
|
|
295
|
-
analysis_result = agent.analysis_agent.analyze_symbol(
|
|
296
|
-
symbol: "RELIANCE",
|
|
297
|
-
exchange_segment: "NSE_EQ"
|
|
298
|
-
)
|
|
299
|
-
|
|
300
|
-
if analysis_result[:error]
|
|
301
|
-
puts " ⚠️ Error: #{analysis_result[:error]}"
|
|
302
|
-
elsif analysis_result[:analysis].nil? || analysis_result[:analysis].empty?
|
|
303
|
-
puts " ⚠️ Error: Analysis returned empty result"
|
|
304
|
-
else
|
|
305
|
-
analysis = analysis_result[:analysis]
|
|
306
|
-
puts " ✅ Analysis Complete"
|
|
307
|
-
puts " 📊 Trend: #{analysis[:trend]&.dig(:trend) || 'N/A'} (#{analysis[:trend]&.dig(:strength) || 0}% strength)"
|
|
308
|
-
puts " 📊 RSI: #{analysis[:indicators]&.dig(:rsi)&.round(2) || 'N/A'}"
|
|
309
|
-
puts " 📊 MACD: #{analysis[:indicators]&.dig(:macd)&.round(2) || 'N/A'}"
|
|
310
|
-
puts " 📊 Current Price: #{analysis[:current_price] || 'N/A'}"
|
|
311
|
-
puts " 📊 Patterns Detected: #{analysis[:patterns]&.dig(:candlestick)&.length || 0} candlestick patterns"
|
|
312
|
-
puts " 📊 Structure Break: #{analysis[:structure_break]&.dig(:broken) ? 'Yes' : 'No'}"
|
|
313
|
-
|
|
314
|
-
# Generate swing trading recommendation
|
|
315
|
-
begin
|
|
316
|
-
recommendation = agent.analysis_agent.generate_recommendation(
|
|
317
|
-
analysis_result,
|
|
318
|
-
trading_style: :swing
|
|
319
|
-
)
|
|
320
|
-
|
|
321
|
-
if recommendation && !recommendation[:error] && recommendation.is_a?(Hash)
|
|
322
|
-
puts "\n 💡 Swing Trading Recommendation:"
|
|
323
|
-
puts " Action: #{recommendation['recommendation']&.upcase || 'N/A'}"
|
|
324
|
-
puts " Entry: #{recommendation['entry_price'] || 'N/A'}"
|
|
325
|
-
puts " Stop Loss: #{recommendation['stop_loss'] || 'N/A'}"
|
|
326
|
-
puts " Target: #{recommendation['target_price'] || 'N/A'}"
|
|
327
|
-
puts " Risk/Reward: #{recommendation['risk_reward_ratio']&.round(2) || 'N/A'}"
|
|
328
|
-
puts " Confidence: #{(recommendation['confidence'] * 100).round}%" if recommendation["confidence"]
|
|
329
|
-
end
|
|
330
|
-
rescue StandardError => e
|
|
331
|
-
puts " ⚠️ Could not generate recommendation: #{e.message}"
|
|
332
|
-
end
|
|
333
|
-
end
|
|
334
|
-
rescue StandardError => e
|
|
335
|
-
puts " ❌ Error: #{e.message}"
|
|
336
|
-
puts " #{e.backtrace.first(3).join("\n ")}" if e.backtrace
|
|
337
|
-
end
|
|
338
|
-
|
|
339
|
-
puts
|
|
340
|
-
puts "Example 2: Swing Trading Scanner"
|
|
341
|
-
puts "─" * 60
|
|
342
|
-
|
|
343
|
-
begin
|
|
344
|
-
# Scan a few symbols for swing opportunities
|
|
345
|
-
symbols_to_scan = ["RELIANCE", "TCS", "INFY"]
|
|
346
|
-
puts " 🔍 Scanning #{symbols_to_scan.length} symbols for swing opportunities..."
|
|
347
|
-
|
|
348
|
-
candidates = agent.swing_scanner.scan_symbols(
|
|
349
|
-
symbols_to_scan,
|
|
350
|
-
exchange_segment: "NSE_EQ",
|
|
351
|
-
min_score: 40,
|
|
352
|
-
verbose: true
|
|
353
|
-
)
|
|
354
|
-
|
|
355
|
-
if candidates.empty?
|
|
356
|
-
puts " ⚠️ No swing candidates found above minimum score (40/100)"
|
|
357
|
-
puts " Try lowering min_score or check rejected candidates above"
|
|
358
|
-
else
|
|
359
|
-
puts " ✅ Found #{candidates.length} swing candidates:"
|
|
360
|
-
candidates.each do |candidate|
|
|
361
|
-
puts " 📈 #{candidate[:symbol]}: Score #{candidate[:score]}/100"
|
|
362
|
-
if candidate[:score_details]
|
|
363
|
-
details = candidate[:score_details]
|
|
364
|
-
puts " Breakdown: #{format_score_breakdown(details)}"
|
|
365
|
-
end
|
|
366
|
-
trend = candidate[:analysis][:trend]
|
|
367
|
-
puts " Trend: #{trend[:trend]} (#{trend[:strength]}% strength)"
|
|
368
|
-
puts " #{candidate[:interpretation]}"
|
|
369
|
-
end
|
|
370
|
-
end
|
|
371
|
-
rescue StandardError => e
|
|
372
|
-
puts " ❌ Error: #{e.message}"
|
|
373
|
-
puts " #{e.backtrace.first(3).join("\n ")}" if e.backtrace
|
|
374
|
-
end
|
|
375
|
-
|
|
376
|
-
puts
|
|
377
|
-
puts "Example 3: Intraday Options Scanner"
|
|
378
|
-
puts "─" * 60
|
|
379
|
-
|
|
380
|
-
begin
|
|
381
|
-
puts " 🔍 Scanning NIFTY for intraday options opportunities..."
|
|
382
|
-
|
|
383
|
-
options_setups = agent.options_scanner.scan_for_options_setups(
|
|
384
|
-
"NIFTY",
|
|
385
|
-
exchange_segment: "IDX_I",
|
|
386
|
-
min_score: 40,
|
|
387
|
-
verbose: true
|
|
388
|
-
)
|
|
389
|
-
|
|
390
|
-
if options_setups[:error]
|
|
391
|
-
puts " ⚠️ #{options_setups[:error]}"
|
|
392
|
-
elsif options_setups[:setups] && !options_setups[:setups].empty?
|
|
393
|
-
puts " ✅ Found #{options_setups[:setups].length} options setups:"
|
|
394
|
-
options_setups[:setups].each do |setup|
|
|
395
|
-
puts " 📊 #{setup[:type].to_s.upcase} @ #{setup[:strike]}"
|
|
396
|
-
puts " #{format_option_setup_details(setup)}"
|
|
397
|
-
puts " Score: #{setup[:score]}/100 | Recommendation: #{setup[:recommendation]}"
|
|
398
|
-
end
|
|
399
|
-
else
|
|
400
|
-
puts " ⚠️ No options setups found above minimum score (40/100)"
|
|
401
|
-
puts " Check rejected setups above or try lowering min_score"
|
|
402
|
-
end
|
|
403
|
-
rescue StandardError => e
|
|
404
|
-
puts " ❌ Error: #{e.message}"
|
|
405
|
-
puts " #{e.backtrace.first(3).join("\n ")}" if e.backtrace
|
|
406
|
-
end
|
|
407
|
-
|
|
408
|
-
end
|
|
409
|
-
|
|
410
|
-
puts
|
|
411
|
-
puts "=" * 60
|
|
412
|
-
puts "Technical Analysis Summary:"
|
|
413
|
-
puts " ✅ Trend Analysis: Uptrend/Downtrend/Sideways detection"
|
|
414
|
-
puts " ✅ Technical Indicators: RSI, MACD, Moving Averages, etc."
|
|
415
|
-
puts " ✅ Pattern Recognition: Candlestick & Chart patterns"
|
|
416
|
-
puts " ✅ Market Structure: SMC concepts, Order blocks, Liquidity zones"
|
|
417
|
-
puts " ✅ Swing Trading Scanner: Find swing opportunities"
|
|
418
|
-
puts " ✅ Intraday Options Scanner: Find options buying setups"
|
|
419
|
-
puts " ✅ LLM Orchestration: AI decides what to analyze"
|
|
420
|
-
puts "=" * 60
|