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,412 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Example: Market Anomaly Detection System
5
+ # This example demonstrates AI-powered anomaly detection for cryptocurrency markets
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 AnomalyMonitor
15
+ def initialize(client, llm_provider = :openai)
16
+ @client = client
17
+ @detector = BudaApi::AI::AnomalyDetector.new(client, llm_provider: llm_provider)
18
+ @monitoring_active = false
19
+ @alert_count = 0
20
+ end
21
+
22
+ def start_monitoring(markets = nil, options = {})
23
+ markets ||= BudaApi::Constants::Market::MAJOR
24
+ @monitoring_active = true
25
+ @alert_count = 0
26
+
27
+ puts "šŸ” Starting Anomaly Detection System"
28
+ puts "Markets: #{markets.join(', ')}"
29
+ puts "=" * 50
30
+
31
+ # Initial scan
32
+ puts "\nšŸ“Š Initial Market Scan"
33
+ puts "-" * 30
34
+
35
+ initial_results = @detector.detect_market_anomalies(
36
+ markets: markets,
37
+ include_ai_analysis: true
38
+ )
39
+
40
+ display_detection_results(initial_results)
41
+
42
+ # Set up continuous monitoring
43
+ if options[:continuous]
44
+ start_continuous_monitoring(markets, options[:interval] || 300)
45
+ end
46
+
47
+ # Set up alerts
48
+ if options[:alerts]
49
+ setup_alert_system(options[:alert_config] || {})
50
+ end
51
+ end
52
+
53
+ def start_continuous_monitoring(markets, interval_seconds)
54
+ puts "\nšŸ”„ Starting Continuous Monitoring"
55
+ puts "Scan interval: #{interval_seconds} seconds"
56
+ puts "Press Ctrl+C to stop monitoring"
57
+ puts "-" * 30
58
+
59
+ begin
60
+ while @monitoring_active
61
+ sleep(interval_seconds)
62
+
63
+ puts "\nā° #{Time.now.strftime('%H:%M:%S')} - Scanning markets..."
64
+
65
+ results = @detector.detect_market_anomalies(
66
+ markets: markets,
67
+ include_ai_analysis: false # Skip AI for frequent scans
68
+ )
69
+
70
+ if results[:anomalies_detected] > 0
71
+ @alert_count += 1
72
+ puts "🚨 ANOMALIES DETECTED (##{@alert_count})"
73
+ display_detection_results(results, compact: true)
74
+ else
75
+ puts "āœ… No anomalies detected"
76
+ end
77
+ end
78
+ rescue Interrupt
79
+ puts "\nā¹ļø Monitoring stopped by user"
80
+ @monitoring_active = false
81
+ end
82
+ end
83
+
84
+ def setup_alert_system(config)
85
+ puts "\n🚨 Setting up Alert System"
86
+ puts "-" * 30
87
+
88
+ alert_system = @detector.setup_anomaly_alerts(config)
89
+ puts "Alert system configured: #{alert_system[:status]}"
90
+ puts "Configuration: #{alert_system[:config]}"
91
+
92
+ alert_system
93
+ end
94
+
95
+ def analyze_single_market(market_id)
96
+ puts "\nšŸ” Deep Market Analysis: #{market_id}"
97
+ puts "-" * 30
98
+
99
+ # Real-time analysis
100
+ current_anomalies = @detector.detect_market_anomalies(
101
+ markets: [market_id],
102
+ include_ai_analysis: true
103
+ )
104
+
105
+ display_detection_results(current_anomalies)
106
+
107
+ # Historical analysis
108
+ puts "\nšŸ“ˆ Historical Anomaly Analysis (24h)"
109
+ puts "-" * 30
110
+
111
+ historical_results = @detector.analyze_historical_anomalies(market_id, 24)
112
+
113
+ if historical_results[:type] == :historical_analysis
114
+ puts "Data Points Analyzed: #{historical_results[:data_points]}"
115
+ puts "Historical Anomalies: #{historical_results[:anomalies_found]}"
116
+
117
+ if historical_results[:anomalies_found] > 0
118
+ puts "\nTop Historical Anomalies:"
119
+ historical_results[:anomalies].first(5).each_with_index do |anomaly, i|
120
+ puts "#{i + 1}. #{anomaly[:type]}: #{anomaly[:description]} (#{anomaly[:severity]})"
121
+ end
122
+ end
123
+ else
124
+ puts "Historical analysis: #{historical_results[:message]}"
125
+ end
126
+ end
127
+
128
+ def display_detection_results(results, compact: false)
129
+ if results[:type] == :anomaly_detection_error
130
+ puts "āŒ Detection Error: #{results[:error]}"
131
+ return
132
+ end
133
+
134
+ puts "Markets Analyzed: #{results[:markets_analyzed]}"
135
+ puts "Anomalies Detected: #{results[:anomalies_detected]}"
136
+
137
+ if results[:anomalies_detected] == 0
138
+ puts "āœ… All markets operating normally"
139
+ return
140
+ end
141
+
142
+ # Display severity summary
143
+ severity = results[:severity_summary]
144
+ if severity[:critical] > 0 || severity[:high] > 0
145
+ puts "🚨 Alert Levels:"
146
+ puts " Critical: #{severity[:critical]}" if severity[:critical] > 0
147
+ puts " High: #{severity[:high]}" if severity[:high] > 0
148
+ puts " Medium: #{severity[:medium]}" if severity[:medium] > 0
149
+ puts " Low: #{severity[:low]}" if severity[:low] > 0
150
+ end
151
+
152
+ # Display top anomalies
153
+ display_count = compact ? 3 : 10
154
+ puts "\nšŸ“‹ Detected Anomalies:"
155
+
156
+ results[:anomalies].first(display_count).each_with_index do |anomaly, i|
157
+ severity_emoji = get_severity_emoji(anomaly[:severity])
158
+
159
+ puts "#{i + 1}. #{severity_emoji} #{anomaly[:market_id]} - #{anomaly[:type].to_s.upcase}"
160
+ puts " #{anomaly[:description]}"
161
+ puts " Severity: #{anomaly[:severity]} (#{anomaly[:severity_score].round(1)})"
162
+
163
+ unless compact
164
+ if anomaly[:recommendation]
165
+ puts " šŸ’” #{anomaly[:recommendation]}"
166
+ end
167
+
168
+ if anomaly[:details]
169
+ display_anomaly_details(anomaly[:details])
170
+ end
171
+ end
172
+
173
+ puts
174
+ end
175
+
176
+ # Display recommendations
177
+ if results[:recommendations].any? && !compact
178
+ puts "šŸ’” General Recommendations:"
179
+ results[:recommendations].each do |rec|
180
+ puts " • #{rec}"
181
+ end
182
+ puts
183
+ end
184
+
185
+ # Display AI analysis if available
186
+ if results[:ai_analysis] && !compact
187
+ puts "🧠 AI Analysis:"
188
+ puts results[:ai_analysis][:analysis]
189
+ puts
190
+ end
191
+ end
192
+
193
+ def get_severity_emoji(severity)
194
+ case severity
195
+ when :critical then "🚫"
196
+ when :high then "šŸ”“"
197
+ when :medium then "🟔"
198
+ when :low then "🟢"
199
+ else "ā“"
200
+ end
201
+ end
202
+
203
+ def display_anomaly_details(details)
204
+ case
205
+ when details[:current_price]
206
+ puts " Price: #{details[:current_price]} CLP"
207
+ puts " Change: #{details[:change_24h]}%" if details[:change_24h]
208
+ when details[:current_volume]
209
+ puts " Volume: #{details[:current_volume]}"
210
+ puts " Ratio: #{details[:volume_ratio]}x normal" if details[:volume_ratio]
211
+ when details[:current_spread]
212
+ puts " Spread: #{details[:current_spread]}%"
213
+ puts " Normal: #{details[:normal_spread]}%" if details[:normal_spread]
214
+ when details[:large_orders]
215
+ puts " Large Orders: #{details[:large_orders].length}"
216
+ puts " Total Value: #{details[:total_value].round(2)} CLP" if details[:total_value]
217
+ end
218
+ end
219
+
220
+ def generate_anomaly_report
221
+ puts "\nšŸ“Š Anomaly Detection Report"
222
+ puts "=" * 50
223
+
224
+ # Generate comprehensive report
225
+ markets = BudaApi::Constants::Market::MAJOR
226
+
227
+ full_results = @detector.detect_market_anomalies(
228
+ markets: markets,
229
+ include_ai_analysis: true
230
+ )
231
+
232
+ display_detection_results(full_results)
233
+
234
+ # Save report to file
235
+ timestamp = Time.now.strftime("%Y%m%d_%H%M%S")
236
+ filename = "anomaly_report_#{timestamp}.json"
237
+
238
+ File.write(filename, JSON.pretty_generate(full_results))
239
+ puts "šŸ“„ Full report saved to: #{filename}"
240
+
241
+ full_results
242
+ end
243
+ end
244
+
245
+ def main
246
+ puts "šŸ” Market Anomaly Detection System"
247
+ puts "=" * 50
248
+
249
+ unless BudaApi.ai_available?
250
+ puts "āŒ AI features not available. Install ruby_llm gem first."
251
+ return
252
+ end
253
+
254
+ # Initialize client and monitor
255
+ client = BudaApi::AuthenticatedClient.new(
256
+ api_key: API_KEY,
257
+ api_secret: API_SECRET,
258
+ sandbox: true
259
+ )
260
+
261
+ monitor = AnomalyMonitor.new(client, :openai)
262
+
263
+ puts "Select monitoring mode:"
264
+ puts "1. One-time scan (default)"
265
+ puts "2. Continuous monitoring"
266
+ puts "3. Single market analysis"
267
+ puts "4. Generate full report"
268
+ print "Choice (1-4): "
269
+
270
+ choice = gets.chomp
271
+
272
+ case choice
273
+ when '2'
274
+ # Continuous monitoring
275
+ puts "\nContinuous monitoring setup:"
276
+ print "Scan interval (seconds, default 300): "
277
+ interval = gets.chomp.to_i
278
+ interval = 300 if interval <= 0
279
+
280
+ monitor.start_monitoring(
281
+ nil, # Use default markets
282
+ continuous: true,
283
+ interval: interval,
284
+ alerts: true
285
+ )
286
+
287
+ when '3'
288
+ # Single market analysis
289
+ puts "\nAvailable markets: #{BudaApi::Constants::Market::MAJOR.join(', ')}"
290
+ print "Enter market ID (e.g., BTC-CLP): "
291
+ market_id = gets.chomp.upcase
292
+
293
+ if BudaApi::Constants::Market::MAJOR.include?(market_id)
294
+ monitor.analyze_single_market(market_id)
295
+ else
296
+ puts "āŒ Invalid market ID"
297
+ end
298
+
299
+ when '4'
300
+ # Generate full report
301
+ monitor.generate_anomaly_report
302
+
303
+ else
304
+ # One-time scan (default)
305
+ monitor.start_monitoring(
306
+ BudaApi::Constants::Market::MAJOR,
307
+ continuous: false
308
+ )
309
+ end
310
+
311
+ rescue BudaApi::ApiError => e
312
+ puts "āŒ API Error: #{e.message}"
313
+ rescue Interrupt
314
+ puts "\nā¹ļø Monitoring stopped"
315
+ rescue => e
316
+ puts "āŒ Error: #{e.message}"
317
+ puts e.backtrace.first(3).join("\n") if ENV['DEBUG']
318
+ end
319
+
320
+ def demo_mode
321
+ puts "\nšŸŽ­ Demo Mode - Simulated Anomaly Detection"
322
+ puts "=" * 50
323
+
324
+ # Simulate some anomalies for demonstration
325
+ simulated_anomalies = [
326
+ {
327
+ type: :price_spike,
328
+ market_id: "BTC-CLP",
329
+ severity: :high,
330
+ severity_score: 8.2,
331
+ description: "Price spike detected: +12.5% change",
332
+ recommendation: "Monitor for potential reversal or continuation",
333
+ timestamp: Time.now
334
+ },
335
+ {
336
+ type: :volume_anomaly,
337
+ market_id: "ETH-CLP",
338
+ severity: :medium,
339
+ severity_score: 6.1,
340
+ description: "Volume anomaly: 4.2x normal volume",
341
+ recommendation: "Watch for breaking news or large transactions",
342
+ timestamp: Time.now
343
+ },
344
+ {
345
+ type: :whale_activity,
346
+ market_id: "BTC-CLP",
347
+ severity: :high,
348
+ severity_score: 7.8,
349
+ description: "Large order activity detected: 3 whale orders",
350
+ recommendation: "Expect potential price impact from large orders",
351
+ timestamp: Time.now
352
+ }
353
+ ]
354
+
355
+ simulated_results = {
356
+ type: :anomaly_detection,
357
+ timestamp: Time.now,
358
+ markets_analyzed: 3,
359
+ anomalies_detected: 3,
360
+ anomalies: simulated_anomalies,
361
+ severity_summary: { critical: 0, high: 2, medium: 1, low: 0 },
362
+ recommendations: [
363
+ "🚨 Multiple high-severity anomalies detected",
364
+ "šŸ‹ Large order activity - monitor for price impact",
365
+ "šŸ“Š Increased market volatility - use caution with orders"
366
+ ]
367
+ }
368
+
369
+ puts "šŸ“Š Simulated Detection Results:"
370
+
371
+ monitor = Object.new
372
+ monitor.define_singleton_method(:display_detection_results) do |results, compact: false|
373
+ # Use the same display logic as the real monitor
374
+ puts "Markets Analyzed: #{results[:markets_analyzed]}"
375
+ puts "Anomalies Detected: #{results[:anomalies_detected]}"
376
+
377
+ puts "\n🚨 Alert Levels:"
378
+ severity = results[:severity_summary]
379
+ puts " High: #{severity[:high]}" if severity[:high] > 0
380
+ puts " Medium: #{severity[:medium]}" if severity[:medium] > 0
381
+
382
+ puts "\nšŸ“‹ Detected Anomalies:"
383
+ results[:anomalies].each_with_index do |anomaly, i|
384
+ severity_emoji = case anomaly[:severity]
385
+ when :high then "šŸ”“"
386
+ when :medium then "🟔"
387
+ else "🟢"
388
+ end
389
+
390
+ puts "#{i + 1}. #{severity_emoji} #{anomaly[:market_id]} - #{anomaly[:type].to_s.upcase}"
391
+ puts " #{anomaly[:description]}"
392
+ puts " šŸ’” #{anomaly[:recommendation]}"
393
+ puts
394
+ end
395
+
396
+ puts "šŸ’” Recommendations:"
397
+ results[:recommendations].each { |rec| puts " • #{rec}" }
398
+ end
399
+
400
+ monitor.display_detection_results(simulated_results)
401
+
402
+ puts "\nšŸŽÆ This is a demonstration of the anomaly detection system."
403
+ puts "In real mode, it would analyze actual market data from the Buda API."
404
+ end
405
+
406
+ if __FILE__ == $0
407
+ if ARGV.include?('--demo')
408
+ demo_mode
409
+ else
410
+ main
411
+ end
412
+ end