buda_api 1.0.0 → 1.0.1

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.
@@ -0,0 +1,605 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Example: AI-Powered Report Generation
5
+ # This example demonstrates automated report generation with AI analysis
6
+
7
+ require 'bundler/setup'
8
+ require_relative '../../lib/buda_api'
9
+
10
+ # Configuration
11
+ API_KEY = ENV['BUDA_API_KEY'] || 'your_api_key_here'
12
+ API_SECRET = ENV['BUDA_API_SECRET'] || 'your_api_secret_here'
13
+
14
+ class ReportingDashboard
15
+ def initialize(client, llm_provider = :openai)
16
+ @client = client
17
+ @reporter = BudaApi::AI::ReportGenerator.new(client, llm_provider: llm_provider)
18
+ end
19
+
20
+ def show_main_menu
21
+ puts "\nšŸ“Š AI Report Generation Dashboard"
22
+ puts "=" * 50
23
+ puts "1. Portfolio Summary Report"
24
+ puts "2. Trading Performance Report"
25
+ puts "3. Market Analysis Report"
26
+ puts "4. Custom AI Report"
27
+ puts "5. Risk Assessment Report"
28
+ puts "6. Generate All Reports"
29
+ puts "7. Export Reports"
30
+ puts "0. Exit"
31
+ puts "-" * 50
32
+ print "Select option (0-7): "
33
+
34
+ choice = gets.chomp
35
+
36
+ case choice
37
+ when '1' then generate_portfolio_summary
38
+ when '2' then generate_trading_performance
39
+ when '3' then generate_market_analysis
40
+ when '4' then generate_custom_report
41
+ when '5' then generate_risk_assessment
42
+ when '6' then generate_all_reports
43
+ when '7' then export_reports_menu
44
+ when '0' then exit_dashboard
45
+ else
46
+ puts "Invalid option. Please try again."
47
+ show_main_menu
48
+ end
49
+ end
50
+
51
+ def generate_portfolio_summary
52
+ puts "\nšŸ’° Generating Portfolio Summary Report..."
53
+ puts "-" * 40
54
+
55
+ # Get format preference
56
+ format = select_report_format
57
+
58
+ report = @reporter.generate_portfolio_summary(
59
+ format: format,
60
+ include_ai: true
61
+ )
62
+
63
+ if report[:type] == :portfolio_summary_report
64
+ display_portfolio_report(report)
65
+ @last_report = report
66
+ else
67
+ puts "āŒ #{report[:error] || report[:message]}"
68
+ end
69
+
70
+ pause_and_return
71
+ end
72
+
73
+ def generate_trading_performance
74
+ puts "\nšŸ“ˆ Generating Trading Performance Report..."
75
+ puts "-" * 40
76
+
77
+ # Get market selection
78
+ puts "Select market:"
79
+ puts "1. All markets (default)"
80
+ puts "2. BTC-CLP only"
81
+ puts "3. ETH-CLP only"
82
+ puts "4. Custom market"
83
+ print "Choice (1-4): "
84
+
85
+ choice = gets.chomp
86
+ market_id = case choice
87
+ when '2' then 'BTC-CLP'
88
+ when '3' then 'ETH-CLP'
89
+ when '4'
90
+ print "Enter market ID: "
91
+ gets.chomp.upcase
92
+ else
93
+ 'all'
94
+ end
95
+
96
+ format = select_report_format
97
+
98
+ report = @reporter.generate_trading_performance(
99
+ market_id,
100
+ format: format,
101
+ limit: 50,
102
+ include_ai: true
103
+ )
104
+
105
+ if report[:type] == :trading_performance_report
106
+ display_trading_report(report)
107
+ @last_report = report
108
+ else
109
+ puts "āŒ #{report[:error] || report[:message]}"
110
+ end
111
+
112
+ pause_and_return
113
+ end
114
+
115
+ def generate_market_analysis
116
+ puts "\nšŸ“Š Generating Market Analysis Report..."
117
+ puts "-" * 40
118
+
119
+ markets = BudaApi::Constants::Market::MAJOR
120
+ format = select_report_format
121
+
122
+ report = @reporter.generate_market_analysis(
123
+ markets,
124
+ format: format,
125
+ include_ai: true
126
+ )
127
+
128
+ if report[:type] == :market_analysis_report
129
+ display_market_report(report)
130
+ @last_report = report
131
+ else
132
+ puts "āŒ #{report[:error] || report[:message]}"
133
+ end
134
+
135
+ pause_and_return
136
+ end
137
+
138
+ def generate_custom_report
139
+ puts "\n🧠 Custom AI Report Generation"
140
+ puts "-" * 40
141
+
142
+ puts "What would you like me to analyze and report on?"
143
+ puts "Example prompts:"
144
+ puts "• 'Analyze my portfolio diversification and suggest improvements'"
145
+ puts "• 'Compare Bitcoin and Ethereum performance this week'"
146
+ puts "• 'Generate investment recommendations for Chilean market'"
147
+ puts "• 'Assess current market volatility and risks'"
148
+ puts
149
+ print "Your custom prompt: "
150
+
151
+ prompt = gets.chomp
152
+
153
+ if prompt.strip.empty?
154
+ puts "āŒ Please provide a prompt for the custom report"
155
+ return generate_custom_report
156
+ end
157
+
158
+ # Select data sources
159
+ puts "\nWhat data should I include?"
160
+ puts "1. Portfolio only"
161
+ puts "2. Market data only"
162
+ puts "3. Trading history only"
163
+ puts "4. All available data (default)"
164
+ print "Choice (1-4): "
165
+
166
+ choice = gets.chomp
167
+ data_sources = case choice
168
+ when '1' then [:portfolio]
169
+ when '2' then [:market]
170
+ when '3' then [:trades]
171
+ else [:portfolio, :market, :trades]
172
+ end
173
+
174
+ format = select_report_format
175
+
176
+ puts "\nšŸ¤– Generating custom analysis..."
177
+
178
+ report = @reporter.generate_custom_report(
179
+ prompt,
180
+ data_sources,
181
+ format: format
182
+ )
183
+
184
+ if report[:type] == :custom_report
185
+ display_custom_report(report)
186
+ @last_report = report
187
+ else
188
+ puts "āŒ #{report[:error] || report[:message]}"
189
+ end
190
+
191
+ pause_and_return
192
+ end
193
+
194
+ def generate_risk_assessment
195
+ puts "\nāš ļø Generating Risk Assessment Report..."
196
+ puts "-" * 40
197
+
198
+ # Use risk manager for comprehensive risk analysis
199
+ risk_manager = BudaApi::AI::RiskManager.new(@client)
200
+
201
+ risk_analysis = risk_manager.analyze_portfolio_risk(include_ai_insights: true)
202
+
203
+ if risk_analysis[:type] == :portfolio_risk_analysis
204
+ display_risk_report(risk_analysis)
205
+
206
+ # Convert to report format
207
+ @last_report = {
208
+ type: :risk_assessment_report,
209
+ format: "text",
210
+ data: risk_analysis,
211
+ timestamp: Time.now
212
+ }
213
+ else
214
+ puts "āŒ #{risk_analysis[:error] || risk_analysis[:message]}"
215
+ end
216
+
217
+ pause_and_return
218
+ end
219
+
220
+ def generate_all_reports
221
+ puts "\nšŸ“‹ Generating Complete Report Suite..."
222
+ puts "=" * 50
223
+
224
+ reports = {}
225
+
226
+ # Generate each report type
227
+ report_types = [
228
+ { name: "Portfolio Summary", method: :generate_portfolio_summary_silent },
229
+ { name: "Trading Performance", method: :generate_trading_performance_silent },
230
+ { name: "Market Analysis", method: :generate_market_analysis_silent }
231
+ ]
232
+
233
+ report_types.each do |report_type|
234
+ puts "šŸ“Š Generating #{report_type[:name]}..."
235
+
236
+ begin
237
+ report = send(report_type[:method])
238
+ reports[report_type[:name]] = report
239
+ puts " āœ… Complete"
240
+ rescue => e
241
+ puts " āŒ Failed: #{e.message}"
242
+ end
243
+ end
244
+
245
+ # Display summary
246
+ puts "\nšŸ“‹ Report Generation Summary"
247
+ puts "-" * 30
248
+
249
+ reports.each do |name, report|
250
+ status = report && report[:formatted_content] ? "āœ…" : "āŒ"
251
+ puts "#{status} #{name}"
252
+ end
253
+
254
+ # Save all reports
255
+ if reports.any?
256
+ puts "\nšŸ’¾ Saving reports to files..."
257
+ save_all_reports(reports)
258
+ end
259
+
260
+ pause_and_return
261
+ end
262
+
263
+ def export_reports_menu
264
+ unless @last_report
265
+ puts "āŒ No report available to export. Generate a report first."
266
+ return pause_and_return
267
+ end
268
+
269
+ puts "\nšŸ’¾ Export Report"
270
+ puts "-" * 20
271
+ puts "Current report: #{@last_report[:type]}"
272
+ puts "Current format: #{@last_report[:format]}"
273
+ puts
274
+ puts "Export options:"
275
+ puts "1. Save current format"
276
+ puts "2. Export as Markdown"
277
+ puts "3. Export as HTML"
278
+ puts "4. Export as JSON"
279
+ puts "5. Export as CSV"
280
+ print "Choice (1-5): "
281
+
282
+ choice = gets.chomp
283
+
284
+ export_format = case choice
285
+ when '2' then 'markdown'
286
+ when '3' then 'html'
287
+ when '4' then 'json'
288
+ when '5' then 'csv'
289
+ else @last_report[:format]
290
+ end
291
+
292
+ # Generate filename
293
+ timestamp = Time.now.strftime("%Y%m%d_%H%M%S")
294
+ report_type = @last_report[:type].to_s.gsub('_report', '').gsub('_', '-')
295
+ extension = get_file_extension(export_format)
296
+ filename = "buda-#{report_type}-#{timestamp}.#{extension}"
297
+
298
+ # Export report
299
+ export_result = @reporter.export_report(@last_report, filename)
300
+
301
+ if export_result[:type] == :export_success
302
+ puts "āœ… Report exported successfully!"
303
+ puts " File: #{export_result[:filename]}"
304
+ puts " Size: #{export_result[:size]} bytes"
305
+ puts " Format: #{export_result[:format]}"
306
+ else
307
+ puts "āŒ Export failed: #{export_result[:error]}"
308
+ end
309
+
310
+ pause_and_return
311
+ end
312
+
313
+ def exit_dashboard
314
+ puts "\nšŸ‘‹ Goodbye! Happy trading!"
315
+ exit
316
+ end
317
+
318
+ private
319
+
320
+ def select_report_format
321
+ puts "\nSelect report format:"
322
+ puts "1. Markdown (default)"
323
+ puts "2. Plain text"
324
+ puts "3. HTML"
325
+ puts "4. JSON"
326
+ print "Choice (1-4): "
327
+
328
+ choice = gets.chomp
329
+
330
+ case choice
331
+ when '2' then 'text'
332
+ when '3' then 'html'
333
+ when '4' then 'json'
334
+ else 'markdown'
335
+ end
336
+ end
337
+
338
+ def display_portfolio_report(report)
339
+ puts "\nšŸ’° Portfolio Summary Report"
340
+ puts "=" * 40
341
+ puts "Generated: #{report[:data][:generated_at]}"
342
+
343
+ if report[:data][:summary]
344
+ summary = report[:data][:summary]
345
+ puts "Total Value: #{summary[:total_value].round(2)} CLP"
346
+ puts "Assets: #{summary[:asset_count]}"
347
+ puts "24h Change: #{summary[:total_change_24h].round(2)}%" if summary[:total_change_24h]
348
+ puts "Top Holding: #{summary[:top_holding]}" if summary[:top_holding]
349
+ end
350
+
351
+ # Show formatted content (first 500 chars)
352
+ if report[:formatted_content]
353
+ puts "\nReport Preview:"
354
+ puts "-" * 20
355
+ content_preview = report[:formatted_content][0, 500]
356
+ content_preview += "..." if report[:formatted_content].length > 500
357
+ puts content_preview
358
+ end
359
+ end
360
+
361
+ def display_trading_report(report)
362
+ puts "\nšŸ“ˆ Trading Performance Report"
363
+ puts "=" * 40
364
+ puts "Generated: #{report[:data][:generated_at]}"
365
+ puts "Market: #{report[:data][:market_id]}"
366
+
367
+ if report[:data][:performance]
368
+ perf = report[:data][:performance]
369
+ puts "Total Trades: #{perf[:total_trades]}"
370
+ puts "Win Rate: #{perf[:win_rate].round(1)}%"
371
+ puts "Total Volume: #{perf[:total_volume].round(2)} CLP"
372
+ puts "Total Fees: #{perf[:total_fees].round(2)} CLP"
373
+ end
374
+
375
+ # Show AI insights if available
376
+ if report[:data][:ai_insights]
377
+ puts "\n🧠 AI Insights:"
378
+ puts report[:data][:ai_insights][:content]
379
+ end
380
+ end
381
+
382
+ def display_market_report(report)
383
+ puts "\nšŸ“Š Market Analysis Report"
384
+ puts "=" * 40
385
+ puts "Generated: #{report[:data][:generated_at]}"
386
+ puts "Markets: #{report[:data][:markets_analyzed]}"
387
+
388
+ if report[:data][:summary]
389
+ summary = report[:data][:summary]
390
+ puts "Markets Up: #{summary[:markets_up]}"
391
+ puts "Markets Down: #{summary[:markets_down]}"
392
+ puts "Sentiment: #{summary[:market_sentiment]}"
393
+ end
394
+
395
+ if report[:data][:ai_insights]
396
+ puts "\n🧠 AI Market Insights:"
397
+ puts report[:data][:ai_insights][:content]
398
+ end
399
+ end
400
+
401
+ def display_custom_report(report)
402
+ puts "\n🧠 Custom AI Report"
403
+ puts "=" * 40
404
+ puts "Generated: #{report[:data][:generated_at]}"
405
+ puts "Prompt: #{report[:data][:prompt]}"
406
+ puts "Data Sources: #{report[:data][:data_sources].join(', ')}"
407
+
408
+ if report[:data][:ai_analysis]
409
+ puts "\nšŸ“‹ AI Analysis:"
410
+ puts report[:data][:ai_analysis][:content]
411
+ end
412
+ end
413
+
414
+ def display_risk_report(risk_analysis)
415
+ puts "\nāš ļø Portfolio Risk Assessment"
416
+ puts "=" * 40
417
+ puts "Generated: #{risk_analysis[:timestamp]}"
418
+ puts "Portfolio Value: #{risk_analysis[:portfolio_value].round(2)} CLP"
419
+ puts "Risk Level: #{risk_analysis[:overall_risk][:color]} #{risk_analysis[:overall_risk][:level]}"
420
+ puts "Risk Score: #{risk_analysis[:overall_risk][:score].round(1)}/5.0"
421
+
422
+ if risk_analysis[:recommendations].any?
423
+ puts "\nRecommendations:"
424
+ risk_analysis[:recommendations].each do |rec|
425
+ puts "• #{rec[:message]}"
426
+ end
427
+ end
428
+
429
+ if risk_analysis[:ai_insights]
430
+ puts "\n🧠 AI Risk Insights:"
431
+ puts risk_analysis[:ai_insights][:analysis]
432
+ end
433
+ end
434
+
435
+ def generate_portfolio_summary_silent
436
+ @reporter.generate_portfolio_summary(format: "markdown", include_ai: true)
437
+ end
438
+
439
+ def generate_trading_performance_silent
440
+ @reporter.generate_trading_performance('all', format: "markdown", include_ai: true)
441
+ end
442
+
443
+ def generate_market_analysis_silent
444
+ @reporter.generate_market_analysis(BudaApi::Constants::Market::MAJOR, format: "markdown", include_ai: true)
445
+ end
446
+
447
+ def save_all_reports(reports)
448
+ timestamp = Time.now.strftime("%Y%m%d_%H%M%S")
449
+
450
+ reports.each do |name, report|
451
+ next unless report && report[:formatted_content]
452
+
453
+ filename = "buda-#{name.downcase.gsub(' ', '-')}-#{timestamp}.md"
454
+ File.write(filename, report[:formatted_content])
455
+ puts " šŸ’¾ #{filename}"
456
+ end
457
+
458
+ puts "āœ… All reports saved successfully!"
459
+ end
460
+
461
+ def get_file_extension(format)
462
+ case format
463
+ when 'markdown' then 'md'
464
+ when 'html' then 'html'
465
+ when 'json' then 'json'
466
+ when 'csv' then 'csv'
467
+ else 'txt'
468
+ end
469
+ end
470
+
471
+ def pause_and_return
472
+ puts "\nPress Enter to return to main menu..."
473
+ gets
474
+ show_main_menu
475
+ end
476
+ end
477
+
478
+ def main
479
+ puts "šŸ“Š AI Report Generation System"
480
+ puts "=" * 50
481
+
482
+ unless BudaApi.ai_available?
483
+ puts "āŒ AI features not available. Install ruby_llm gem first."
484
+ return
485
+ end
486
+
487
+ # Initialize client and dashboard
488
+ client = BudaApi::AuthenticatedClient.new(
489
+ api_key: API_KEY,
490
+ api_secret: API_SECRET,
491
+ sandbox: true
492
+ )
493
+
494
+ dashboard = ReportingDashboard.new(client, :openai)
495
+ dashboard.show_main_menu
496
+
497
+ rescue BudaApi::ApiError => e
498
+ puts "āŒ API Error: #{e.message}"
499
+ rescue => e
500
+ puts "āŒ Error: #{e.message}"
501
+ puts e.backtrace.first(3).join("\n") if ENV['DEBUG']
502
+ end
503
+
504
+ def demo_reports
505
+ puts "\nšŸŽ­ Demo Report Generation"
506
+ puts "=" * 50
507
+
508
+ # Generate sample reports with mock data
509
+ reports = {
510
+ "Portfolio Summary" => generate_demo_portfolio_report,
511
+ "Market Analysis" => generate_demo_market_report,
512
+ "Trading Performance" => generate_demo_trading_report
513
+ }
514
+
515
+ reports.each do |name, content|
516
+ filename = "demo-#{name.downcase.gsub(' ', '-')}.md"
517
+ File.write(filename, content)
518
+ puts "šŸ“„ Generated: #{filename}"
519
+ end
520
+
521
+ puts "\nāœ… Demo reports generated successfully!"
522
+ puts "These reports show the format and structure of AI-generated content."
523
+ end
524
+
525
+ def generate_demo_portfolio_report
526
+ """# Portfolio Summary Report
527
+ *Generated: #{Time.now}*
528
+
529
+ ## Overview
530
+ - **Total Portfolio Value:** 2,500,000 CLP
531
+ - **Number of Assets:** 4
532
+ - **24h Change:** +3.2% (+80,000 CLP)
533
+
534
+ ## Holdings
535
+ | Asset | Amount | Value (CLP) | Allocation |
536
+ |-------|---------|-------------|------------|
537
+ | BTC | 0.0125 | 1,250,000 | 50.0% |
538
+ | ETH | 0.75 | 750,000 | 30.0% |
539
+ | CLP | 400,000 | 400,000 | 16.0% |
540
+ | USDC | 100 | 100,000 | 4.0% |
541
+
542
+ ## Market Performance
543
+ | Market | Price | 24h Change | Volume |
544
+ |--------|-------|------------|--------|
545
+ | BTC-CLP | 100,000,000 | +2.5% | 15,000,000 |
546
+ | ETH-CLP | 1,000,000 | +4.1% | 8,500,000 |
547
+
548
+ ## AI Analysis
549
+ Your portfolio shows strong performance with a healthy 3.2% gain over 24 hours. The 50% Bitcoin allocation provides good stability, while the 30% Ethereum position offers growth potential. Consider reducing the high concentration in BTC by diversifying into other cryptocurrencies. The 16% CLP position provides good liquidity for opportunities. Overall risk level is moderate with good upside potential in the current market conditions.
550
+ """
551
+ end
552
+
553
+ def generate_demo_market_report
554
+ """# Market Analysis Report
555
+ *Generated: #{Time.now}*
556
+
557
+ ## Market Overview
558
+ - **Markets Analyzed:** 5
559
+ - **Overall Sentiment:** Bullish
560
+ - **Markets Up:** 4
561
+ - **Markets Down:** 1
562
+
563
+ ## Performance Summary
564
+ | Market | Current Price | 24h Change | Volume | Status |
565
+ |--------|---------------|------------|---------|---------|
566
+ | BTC-CLP | 100,000,000 | +2.5% | 15M | 🟢 Strong |
567
+ | ETH-CLP | 1,000,000 | +4.1% | 8.5M | 🟢 Very Strong |
568
+ | LTC-CLP | 150,000 | +1.8% | 2.1M | 🟢 Moderate |
569
+ | BCH-CLP | 500,000 | -0.5% | 1.8M | šŸ”“ Weak |
570
+
571
+ ## AI Market Insights
572
+ The Chilean cryptocurrency market is showing strong bullish momentum with 80% of major pairs posting gains. Bitcoin's 2.5% increase demonstrates solid institutional confidence, while Ethereum's 4.1% surge indicates strong DeFi activity. Trading volumes are above average, suggesting healthy market participation. The slight weakness in Bitcoin Cash appears to be profit-taking rather than fundamental concerns. Recommend maintaining long positions with trailing stops to capture continued upside while protecting against potential reversals.
573
+ """
574
+ end
575
+
576
+ def generate_demo_trading_report
577
+ """# Trading Performance Report
578
+ *Generated: #{Time.now}*
579
+
580
+ ## Performance Summary
581
+ - **Total Trades:** 25
582
+ - **Winning Trades:** 16 (64%)
583
+ - **Total Volume:** 12,500,000 CLP
584
+ - **Total Fees:** 25,000 CLP
585
+ - **Net P&L:** +125,000 CLP (+1.0%)
586
+
587
+ ## Trading Breakdown
588
+ | Market | Trades | Win Rate | Volume | P&L |
589
+ |---------|---------|----------|---------|------|
590
+ | BTC-CLP | 15 | 67% | 8,000,000 | +85,000 |
591
+ | ETH-CLP | 8 | 63% | 3,500,000 | +35,000 |
592
+ | LTC-CLP | 2 | 50% | 1,000,000 | +5,000 |
593
+
594
+ ## AI Trading Insights
595
+ Your trading performance shows solid discipline with a 64% win rate and positive returns. The focus on BTC-CLP demonstrates good market selection, with your best performance coming from the most liquid market. Consider reducing position sizes on lower-volume markets like LTC-CLP to minimize slippage impact. The fee ratio of 0.2% is reasonable but could be optimized by using more limit orders instead of market orders. Overall strategy appears sound with room for improvement in risk management and position sizing.
596
+ """
597
+ end
598
+
599
+ if __FILE__ == $0
600
+ if ARGV.include?('--demo')
601
+ demo_reports
602
+ else
603
+ main
604
+ end
605
+ end