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.
- checksums.yaml +4 -4
- data/README.md +101 -4
- data/buda_api.gemspec +4 -1
- data/examples/ai/README.md +314 -0
- data/examples/ai/anomaly_detection_example.rb +412 -0
- data/examples/ai/natural_language_trading.rb +369 -0
- data/examples/ai/report_generation_example.rb +605 -0
- data/examples/ai/risk_management_example.rb +300 -0
- data/examples/ai/trading_assistant_example.rb +295 -0
- data/lib/buda_api/ai/anomaly_detector.rb +787 -0
- data/lib/buda_api/ai/natural_language_trader.rb +541 -0
- data/lib/buda_api/ai/report_generator.rb +1054 -0
- data/lib/buda_api/ai/risk_manager.rb +789 -0
- data/lib/buda_api/ai/trading_assistant.rb +404 -0
- data/lib/buda_api/version.rb +1 -1
- data/lib/buda_api.rb +37 -0
- metadata +32 -1
@@ -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
|