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,369 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# Example: Natural Language Trading Interface
|
5
|
+
# This example demonstrates conversational trading using natural language processing
|
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 TradingChatBot
|
15
|
+
def initialize(client, llm_provider = :openai)
|
16
|
+
@client = client
|
17
|
+
@nl_trader = BudaApi.natural_language_trader(client, llm_provider: llm_provider)
|
18
|
+
@conversation_active = true
|
19
|
+
@demo_mode = true # Safety flag
|
20
|
+
|
21
|
+
puts "š¤ AI Trading Assistant initialized!"
|
22
|
+
puts "Demo mode: #{@demo_mode ? 'ON (safe)' : 'OFF (live trading)'}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def start_conversation
|
26
|
+
puts "\nš¬ Natural Language Trading Interface"
|
27
|
+
puts "=" * 50
|
28
|
+
puts "You can ask me about:"
|
29
|
+
puts "⢠Account balances and portfolio status"
|
30
|
+
puts "⢠Current market prices and trends"
|
31
|
+
puts "⢠Trading opportunities and analysis"
|
32
|
+
puts "⢠Risk assessment and recommendations"
|
33
|
+
puts "⢠Market data and order books"
|
34
|
+
puts "⢠Place orders (with confirmation)"
|
35
|
+
puts
|
36
|
+
puts "Type 'help' for more commands, 'exit' to quit"
|
37
|
+
puts "-" * 50
|
38
|
+
|
39
|
+
while @conversation_active
|
40
|
+
print "\nš You: "
|
41
|
+
user_input = gets.chomp.strip
|
42
|
+
|
43
|
+
next if user_input.empty?
|
44
|
+
|
45
|
+
handle_user_input(user_input)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def handle_user_input(input)
|
52
|
+
case input.downcase
|
53
|
+
when 'exit', 'quit', 'bye'
|
54
|
+
puts "š¤ Goodbye! Happy trading! š"
|
55
|
+
@conversation_active = false
|
56
|
+
when 'help'
|
57
|
+
show_help_menu
|
58
|
+
when 'clear', 'reset'
|
59
|
+
@nl_trader.clear_history
|
60
|
+
puts "š¤ Conversation history cleared!"
|
61
|
+
when 'demo on', 'safety on'
|
62
|
+
@demo_mode = true
|
63
|
+
puts "š¤ Demo mode enabled - no real trades will be executed"
|
64
|
+
when 'demo off', 'safety off'
|
65
|
+
puts "ā ļø Are you sure you want to enable live trading? (yes/no)"
|
66
|
+
confirmation = gets.chomp.downcase
|
67
|
+
if confirmation == 'yes'
|
68
|
+
@demo_mode = false
|
69
|
+
puts "š¤ ā ļø LIVE TRADING MODE ENABLED - Real trades will be executed!"
|
70
|
+
else
|
71
|
+
puts "š¤ Demo mode remains enabled"
|
72
|
+
end
|
73
|
+
when /^examples?$/
|
74
|
+
show_example_queries
|
75
|
+
else
|
76
|
+
process_trading_query(input)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def process_trading_query(input)
|
81
|
+
puts "š¤ Processing your request..."
|
82
|
+
|
83
|
+
begin
|
84
|
+
# Execute the natural language command
|
85
|
+
result = @nl_trader.execute_command(input, confirm_trades: !@demo_mode)
|
86
|
+
|
87
|
+
# Handle different response types
|
88
|
+
case result[:type]
|
89
|
+
when :text_response
|
90
|
+
puts "š¤ #{result[:content]}"
|
91
|
+
|
92
|
+
when :balance_info
|
93
|
+
display_balance_info(result)
|
94
|
+
|
95
|
+
when :market_data
|
96
|
+
display_market_data(result)
|
97
|
+
|
98
|
+
when :quotation
|
99
|
+
display_quotation_info(result)
|
100
|
+
|
101
|
+
when :order_history
|
102
|
+
display_order_history(result)
|
103
|
+
|
104
|
+
when :confirmation_required
|
105
|
+
handle_trade_confirmation(result)
|
106
|
+
|
107
|
+
when :order_placed
|
108
|
+
display_order_success(result)
|
109
|
+
|
110
|
+
when :order_cancelled
|
111
|
+
puts "š¤ ā
#{result[:message]}"
|
112
|
+
|
113
|
+
when :error
|
114
|
+
puts "š¤ ā #{result[:error]}"
|
115
|
+
suggest_alternatives(input)
|
116
|
+
|
117
|
+
else
|
118
|
+
puts "š¤ #{result[:message] || 'Request processed'}"
|
119
|
+
end
|
120
|
+
|
121
|
+
rescue BudaApi::ApiError => e
|
122
|
+
puts "š¤ ā API Error: #{e.message}"
|
123
|
+
suggest_api_solutions(e)
|
124
|
+
rescue => e
|
125
|
+
puts "š¤ ā Unexpected error: #{e.message}"
|
126
|
+
puts "Please try rephrasing your request or type 'help' for guidance."
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def display_balance_info(result)
|
131
|
+
puts "š¤ š° Balance Information:"
|
132
|
+
puts " Currency: #{result[:currency]}"
|
133
|
+
puts " Available: #{result[:available]} #{result[:currency]}"
|
134
|
+
puts " Total: #{result[:total]} #{result[:currency]}"
|
135
|
+
|
136
|
+
if result[:frozen] > 0
|
137
|
+
puts " Frozen: #{result[:frozen]} #{result[:currency]}"
|
138
|
+
end
|
139
|
+
|
140
|
+
if result[:pending_withdrawals] > 0
|
141
|
+
puts " Pending Withdrawals: #{result[:pending_withdrawals]} #{result[:currency]}"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def display_market_data(result)
|
146
|
+
change_emoji = result[:change_24h] >= 0 ? "š" : "š"
|
147
|
+
change_color = result[:change_24h] >= 0 ? "+" : ""
|
148
|
+
|
149
|
+
puts "š¤ š Market Data for #{result[:market_id]}:"
|
150
|
+
puts " Current Price: #{result[:price]} CLP"
|
151
|
+
puts " 24h Change: #{change_emoji} #{change_color}#{result[:change_24h].round(2)}%"
|
152
|
+
puts " 24h Volume: #{result[:volume].round(2)}"
|
153
|
+
puts " Best Bid: #{result[:best_bid]} CLP"
|
154
|
+
puts " Best Ask: #{result[:best_ask]} CLP"
|
155
|
+
puts " Spread: #{result[:spread].round(4)}%"
|
156
|
+
end
|
157
|
+
|
158
|
+
def display_quotation_info(result)
|
159
|
+
puts "š¤ š± Price Quotation:"
|
160
|
+
puts " To #{result[:side]} #{result[:amount]} #{result[:market_id].split('-').first}:"
|
161
|
+
puts " Estimated Cost: #{result[:estimated_cost]} CLP"
|
162
|
+
puts " Trading Fee: #{result[:fee]} CLP"
|
163
|
+
puts " Total: #{(result[:estimated_cost].abs + result[:fee]).round(2)} CLP"
|
164
|
+
end
|
165
|
+
|
166
|
+
def display_order_history(result)
|
167
|
+
puts "š¤ š Recent Orders for #{result[:market_id]}:"
|
168
|
+
|
169
|
+
if result[:orders].empty?
|
170
|
+
puts " No recent orders found"
|
171
|
+
return
|
172
|
+
end
|
173
|
+
|
174
|
+
puts " Found #{result[:orders_count]} orders:"
|
175
|
+
puts
|
176
|
+
|
177
|
+
result[:orders].first(5).each do |order|
|
178
|
+
status_emoji = case order[:state]
|
179
|
+
when "traded" then "ā
"
|
180
|
+
when "pending" then "ā³"
|
181
|
+
when "cancelled" then "ā"
|
182
|
+
else "ā"
|
183
|
+
end
|
184
|
+
|
185
|
+
price_info = order[:price] ? "@ #{order[:price]} CLP" : "(market price)"
|
186
|
+
|
187
|
+
puts " #{status_emoji} #{order[:type].upcase} #{order[:amount]} #{price_info}"
|
188
|
+
puts " ID: #{order[:id]} | Status: #{order[:state]} | #{order[:created_at]}"
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def handle_trade_confirmation(result)
|
193
|
+
return execute_demo_trade(result) if @demo_mode
|
194
|
+
|
195
|
+
puts "š¤ ā ļø Trade Confirmation Required:"
|
196
|
+
puts " #{result[:message]}"
|
197
|
+
puts
|
198
|
+
print " Do you want to proceed? (yes/no): "
|
199
|
+
|
200
|
+
confirmation = gets.chomp.downcase
|
201
|
+
|
202
|
+
if %w[yes y confirm].include?(confirmation)
|
203
|
+
puts "š¤ Executing trade..."
|
204
|
+
# In a real implementation, this would execute the confirmed trade
|
205
|
+
puts "ā
Trade executed successfully! (This is a demo)"
|
206
|
+
else
|
207
|
+
puts "š¤ Trade cancelled as requested"
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
def execute_demo_trade(result)
|
212
|
+
puts "š¤ š Demo Trade Simulation:"
|
213
|
+
puts " #{result[:message]}"
|
214
|
+
puts " ā
Would be executed in live mode"
|
215
|
+
puts " š” Enable live trading with 'demo off' command"
|
216
|
+
end
|
217
|
+
|
218
|
+
def display_order_success(result)
|
219
|
+
puts "š¤ ā
Order Placed Successfully!"
|
220
|
+
puts " Order ID: #{result[:order_id]}"
|
221
|
+
puts " Market: #{result[:market_id]}"
|
222
|
+
puts " Side: #{result[:side].upcase}"
|
223
|
+
puts " Amount: #{result[:amount]}"
|
224
|
+
puts " Price: #{result[:price] || 'Market Price'}"
|
225
|
+
puts " Status: #{result[:status]}"
|
226
|
+
end
|
227
|
+
|
228
|
+
def suggest_alternatives(original_input)
|
229
|
+
suggestions = [
|
230
|
+
"Try: 'Check my BTC balance'",
|
231
|
+
"Try: 'What's the current price of Bitcoin?'",
|
232
|
+
"Try: 'Show me the ETH order book'",
|
233
|
+
"Try: 'Get a quote for buying 0.001 BTC'",
|
234
|
+
"Type 'examples' to see more query examples"
|
235
|
+
]
|
236
|
+
|
237
|
+
puts "š¤ š” Here are some things you can try:"
|
238
|
+
suggestions.each { |suggestion| puts " #{suggestion}" }
|
239
|
+
end
|
240
|
+
|
241
|
+
def suggest_api_solutions(error)
|
242
|
+
case error.message
|
243
|
+
when /authentication/i
|
244
|
+
puts "š¤ š” This might be an authentication issue:"
|
245
|
+
puts " ⢠Check your API credentials"
|
246
|
+
puts " ⢠Make sure your API key has the required permissions"
|
247
|
+
when /not found/i
|
248
|
+
puts "š¤ š” This resource might not exist:"
|
249
|
+
puts " ⢠Check market names (e.g., 'BTC-CLP', 'ETH-CLP')"
|
250
|
+
puts " ⢠Verify currency codes are supported"
|
251
|
+
when /rate limit/i
|
252
|
+
puts "š¤ š” API rate limit exceeded:"
|
253
|
+
puts " ⢠Please wait a moment and try again"
|
254
|
+
puts " ⢠Consider spacing out your requests"
|
255
|
+
else
|
256
|
+
puts "š¤ š” You can try:"
|
257
|
+
puts " ⢠Check your internet connection"
|
258
|
+
puts " ⢠Try a different query"
|
259
|
+
puts " ⢠Contact support if the issue persists"
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
def show_help_menu
|
264
|
+
puts """
|
265
|
+
š¤ Trading Assistant Help Menu
|
266
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
267
|
+
|
268
|
+
š° BALANCE QUERIES:
|
269
|
+
⢠"Check my BTC balance"
|
270
|
+
⢠"Show all my balances"
|
271
|
+
⢠"How much Ethereum do I have?"
|
272
|
+
|
273
|
+
š MARKET DATA:
|
274
|
+
⢠"What's the Bitcoin price?"
|
275
|
+
⢠"Show BTC-CLP market data"
|
276
|
+
⢠"Get ETH order book"
|
277
|
+
⢠"What are the current spreads?"
|
278
|
+
|
279
|
+
š± PRICE QUOTES:
|
280
|
+
⢠"Quote for buying 0.001 BTC"
|
281
|
+
⢠"How much to sell 1 ETH?"
|
282
|
+
⢠"Price for 100000 CLP of Bitcoin"
|
283
|
+
|
284
|
+
š ORDER MANAGEMENT:
|
285
|
+
⢠"Show my recent orders"
|
286
|
+
⢠"Cancel order 12345"
|
287
|
+
⢠"Order history for BTC-CLP"
|
288
|
+
|
289
|
+
šÆ TRADING (Demo Mode):
|
290
|
+
⢠"Buy 0.001 BTC at market price"
|
291
|
+
⢠"Sell 0.5 ETH at 2000000 CLP"
|
292
|
+
⢠"Place limit order for Bitcoin"
|
293
|
+
|
294
|
+
š§ ANALYSIS:
|
295
|
+
⢠"Analyze Bitcoin market"
|
296
|
+
⢠"What are good trading opportunities?"
|
297
|
+
⢠"Risk assessment for my portfolio"
|
298
|
+
|
299
|
+
āļø COMMANDS:
|
300
|
+
⢠help - Show this help
|
301
|
+
⢠examples - Show example queries
|
302
|
+
⢠clear - Clear conversation history
|
303
|
+
⢠demo on/off - Toggle trading mode
|
304
|
+
⢠exit - Quit assistant
|
305
|
+
|
306
|
+
š”ļø SAFETY FEATURES:
|
307
|
+
⢠Demo mode prevents real trades
|
308
|
+
⢠All orders require confirmation
|
309
|
+
⢠Clear error messages and suggestions
|
310
|
+
"""
|
311
|
+
end
|
312
|
+
|
313
|
+
def show_example_queries
|
314
|
+
puts """
|
315
|
+
š¤ Example Queries You Can Try
|
316
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
317
|
+
|
318
|
+
š° "Check my Bitcoin balance"
|
319
|
+
š "What's the current price of Ethereum in CLP?"
|
320
|
+
š "Show me the BTC-CLP order book"
|
321
|
+
š± "How much would it cost to buy 0.001 BTC?"
|
322
|
+
š "Show my last 10 orders"
|
323
|
+
šÆ "I want to buy 50000 CLP worth of Bitcoin"
|
324
|
+
š "What's the spread on ETH-CLP?"
|
325
|
+
š "Give me market data for all major coins"
|
326
|
+
š§ "Analyze the Bitcoin market trends"
|
327
|
+
ā ļø "What are the risks in my current portfolio?"
|
328
|
+
š” "What are the best trading opportunities right now?"
|
329
|
+
š² "Should I buy or sell Bitcoin today?"
|
330
|
+
|
331
|
+
Try any of these or ask in your own words!
|
332
|
+
"""
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
def main
|
337
|
+
puts "š Natural Language Trading Interface"
|
338
|
+
puts "=" * 50
|
339
|
+
|
340
|
+
unless BudaApi.ai_available?
|
341
|
+
puts "ā AI features not available. Please install ruby_llm gem:"
|
342
|
+
puts " gem install ruby_llm"
|
343
|
+
return
|
344
|
+
end
|
345
|
+
|
346
|
+
# Initialize client
|
347
|
+
client = BudaApi::AuthenticatedClient.new(
|
348
|
+
api_key: API_KEY,
|
349
|
+
api_secret: API_SECRET,
|
350
|
+
sandbox: true # Use sandbox for safety
|
351
|
+
)
|
352
|
+
|
353
|
+
# Create and start chat bot
|
354
|
+
bot = TradingChatBot.new(client, :openai)
|
355
|
+
bot.start_conversation
|
356
|
+
|
357
|
+
rescue BudaApi::AuthenticationError
|
358
|
+
puts "ā Authentication failed. Please check your API credentials."
|
359
|
+
puts "Set environment variables:"
|
360
|
+
puts " export BUDA_API_KEY='your_key'"
|
361
|
+
puts " export BUDA_API_SECRET='your_secret'"
|
362
|
+
rescue => e
|
363
|
+
puts "ā Error: #{e.message}"
|
364
|
+
puts e.backtrace.first(3).join("\n") if ENV['DEBUG']
|
365
|
+
end
|
366
|
+
|
367
|
+
if __FILE__ == $0
|
368
|
+
main
|
369
|
+
end
|