Class: RbtcArbitrage::Trader
- Inherits:
-
Object
- Object
- RbtcArbitrage::Trader
- Defined in:
- lib/rbtc_arbitrage/trader.rb
Instance Attribute Summary collapse
-
#buy_client ⇒ Object
readonly
Returns the value of attribute buy_client.
-
#buyer ⇒ Object
Returns the value of attribute buyer.
-
#options ⇒ Object
Returns the value of attribute options.
-
#received ⇒ Object
readonly
Returns the value of attribute received.
-
#sell_client ⇒ Object
readonly
Returns the value of attribute sell_client.
-
#seller ⇒ Object
Returns the value of attribute seller.
Instance Method Summary collapse
- #client_for_exchange(market) ⇒ Object
- #execute_trade ⇒ Object
- #fetch_prices ⇒ Object
- #get_balance ⇒ Object
-
#initialize(config = {}) ⇒ Trader
constructor
A new instance of Trader.
- #log_info ⇒ Object
- #logger ⇒ Object
- #notification ⇒ Object
- #notify ⇒ Object
- #set_key(config, key, default) ⇒ Object
- #setup_pony ⇒ Object
- #trade ⇒ Object
- #trade_again ⇒ Object
- #validate_env ⇒ Object
Constructor Details
#initialize(config = {}) ⇒ Trader
Returns a new instance of Trader.
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/rbtc_arbitrage/trader.rb', line 6 def initialize config={} opts = {} config.each do |key, val| opts[(key.to_sym rescue key) || key] = val end @buyer = {} @seller = {} = {} set_key opts, :volume, 0.01 set_key opts, :cutoff, 2 default_logger = Logger.new($stdout) default_logger.datetime_format = "%^b %e %Y %l:%M:%S %p %z" set_key opts, :logger, default_logger set_key opts, :verbose, true set_key opts, :live, false set_key opts, :repeat, nil set_key opts, :notify, false exchange = opts[:buyer] || :bitstamp @buy_client = client_for_exchange(exchange) exchange = opts[:seller] || :campbx @sell_client = client_for_exchange(exchange) self end |
Instance Attribute Details
#buy_client ⇒ Object (readonly)
Returns the value of attribute buy_client.
3 4 5 |
# File 'lib/rbtc_arbitrage/trader.rb', line 3 def buy_client @buy_client end |
#buyer ⇒ Object
Returns the value of attribute buyer.
4 5 6 |
# File 'lib/rbtc_arbitrage/trader.rb', line 4 def buyer @buyer end |
#options ⇒ Object
Returns the value of attribute options.
4 5 6 |
# File 'lib/rbtc_arbitrage/trader.rb', line 4 def end |
#received ⇒ Object (readonly)
Returns the value of attribute received.
3 4 5 |
# File 'lib/rbtc_arbitrage/trader.rb', line 3 def received @received end |
#sell_client ⇒ Object (readonly)
Returns the value of attribute sell_client.
3 4 5 |
# File 'lib/rbtc_arbitrage/trader.rb', line 3 def sell_client @sell_client end |
#seller ⇒ Object
Returns the value of attribute seller.
4 5 6 |
# File 'lib/rbtc_arbitrage/trader.rb', line 4 def seller @seller end |
Instance Method Details
#client_for_exchange(market) ⇒ Object
130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/rbtc_arbitrage/trader.rb', line 130 def client_for_exchange market market = market.to_sym unless market.is_a?(Symbol) clazz = RbtcArbitrage::Clients.constants.find do |c| clazz = RbtcArbitrage::Clients.const_get(c) clazz.new.exchange == market end begin clazz = RbtcArbitrage::Clients.const_get(clazz) clazz.new rescue TypeError => e raise ArgumentError, "Invalid exchange - '#{market}'" end end |
#execute_trade ⇒ Object
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/rbtc_arbitrage/trader.rb', line 61 def execute_trade fetch_prices unless @paid validate_env raise SecurityError, "--live flag is false. Not executing trade." unless [:live] get_balance if @percent > [:cutoff] if @paid > buyer[:usd] || [:volume] > seller[:btc] raise SecurityError, "Not enough funds. Exiting." else logger.info "Trading live!" if [:verbose] @buy_client.buy @sell_client.sell @buy_client.transfer @sell_client end else logger.info "Not trading live because cutoff is higher than profit." if [:verbose] end end |
#fetch_prices ⇒ Object
80 81 82 83 84 85 86 87 88 |
# File 'lib/rbtc_arbitrage/trader.rb', line 80 def fetch_prices logger.info "Fetching exchange rates" if [:verbose] buyer[:price] = @buy_client.price(:buy) seller[:price] = @sell_client.price(:sell) prices = [buyer[:price], seller[:price]] @paid = buyer[:price] * 1.006 * [:volume] @received = seller[:price] * 0.994 * [:volume] @percent = ((received/@paid - 1) * 100).round(2) end |
#get_balance ⇒ Object
106 107 108 109 |
# File 'lib/rbtc_arbitrage/trader.rb', line 106 def get_balance @seller[:btc], @seller[:usd] = @sell_client.balance @buyer[:btc], @buyer[:usd] = @buy_client.balance end |
#log_info ⇒ Object
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/rbtc_arbitrage/trader.rb', line 90 def log_info lower_ex = @buy_client.exchange.to_s.capitalize higher_ex = @sell_client.exchange.to_s.capitalize logger.info "#{lower_ex}: $#{buyer[:price].round(2)}" logger.info "#{higher_ex}: $#{seller[:price].round(2)}" logger.info "buying #{@options[:volume]} btc from #{lower_ex} for $#{@paid.round(2)}" logger.info "selling #{@options[:volume]} btc on #{higher_ex} for $#{@received.round(2)}" profit_msg = "profit: $#{(@received - @paid).round(2)} (#{@percent.round(2)}%)" if cutoff = [:cutoff] profit_msg << " is #{@percent < cutoff ? 'below' : 'above'} cutoff" profit_msg << " of #{cutoff}%." end logger.info profit_msg end |
#logger ⇒ Object
111 112 113 |
# File 'lib/rbtc_arbitrage/trader.rb', line 111 def logger [:logger] end |
#notification ⇒ Object
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/rbtc_arbitrage/trader.rb', line 173 def notification lower_ex = @buy_client.exchange.to_s.capitalize higher_ex = @sell_client.exchange.to_s.capitalize " Update from your friendly rbtc_arbitrage trader:\n\n -------------------\n\n \#{lower_ex}: $\#{buyer[:price].round(2)}\n \#{higher_ex}: $\#{seller[:price].round(2)}\n buying \#{@options[:volume]} btc from \#{lower_ex} for $\#{@paid.round(2)}\n selling \#{@options[:volume]} btc on \#{higher_ex} for $\#{@received.round(2)}\n profit: $\#{(@received - @paid).round(2)} (\#{@percent.round(2)}%)\n\n -------------------\n\n options:\n\n \#{options.reject{|k,v| v.is_a?(Logger)}.collect{|k,v| \"\#{k}: \#{v.to_s}\"}.join(\" | \")}\n\n -------------------\n\n https://github.com/hstove/rbtc_arbitrage\n eos\nend\n" |
#notify ⇒ Object
144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/rbtc_arbitrage/trader.rb', line 144 def notify return false unless [:notify] return false unless @percent > [:cutoff] setup_pony [:logger].info "Sending email to #{ENV['SENDGRID_EMAIL']}" Pony.mail({ body: notification, to: ENV['SENDGRID_EMAIL'], }) end |
#set_key(config, key, default) ⇒ Object
30 31 32 |
# File 'lib/rbtc_arbitrage/trader.rb', line 30 def set_key config, key, default [key] = config.has_key?(key) ? config[key] : default end |
#setup_pony ⇒ Object
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/rbtc_arbitrage/trader.rb', line 156 def setup_pony Pony. = { from: ENV['FROM_EMAIL'] || "[email protected]", subject: "rbtc_arbitrage notification", via: :smtp, via_options: { address: 'smtp.sendgrid.net', port: '587', domain: 'heroku.com', user_name: ENV['SENDGRID_USERNAME'], password: ENV['SENDGRID_PASSWORD'], authentication: :plain, enable_starttls_auto: true } } end |
#trade ⇒ Object
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/rbtc_arbitrage/trader.rb', line 34 def trade fetch_prices log_info if [:verbose] if [:live] && [:cutoff] > @percent raise SecurityError, "Exiting because real profit (#{@percent.round(2)}%) is less than cutoff (#{options[:cutoff].round(2)}%)" end execute_trade if [:live] notify if [:repeat] trade_again end self end |
#trade_again ⇒ Object
53 54 55 56 57 58 59 |
# File 'lib/rbtc_arbitrage/trader.rb', line 53 def trade_again sleep [:repeat] logger.info " - " if [:verbose] @buy_client = @buy_client.class.new() @sell_client = @sell_client.class.new() trade end |
#validate_env ⇒ Object
115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/rbtc_arbitrage/trader.rb', line 115 def validate_env [@sell_client, @buy_client].each do |client| client.validate_env end if [:notify] ["PASSWORD","USERNAME","EMAIL"].each do |key| key = "SENDGRID_#{key}" unless ENV[key] raise ArgumentError, "Exiting because missing required ENV variable $#{key}." end end setup_pony end end |