|
## Altcoin Watcher 0.1.1 |
|
# |
|
# Watch altcoin Prices & Win revenue from your shell |
|
# Used APIs: |
|
# - Crytofolio.info |
|
# - Cryptsy.com |
|
# |
|
# (c) 2013-2014 Roman Pramberger ([email protected]) |
|
# License: MIT http://opensource.org/licenses/MIT |
|
# |
|
|
|
require 'open-uri' |
|
require 'net/http' |
|
|
|
## Config |
|
|
|
DECIMAL_LEN = 8 # length after comma |
|
REDRAW_TIMEOUT = 30 # redraw screen timeout in seconds |
|
TIMELINE = false # show "time line" |
|
|
|
# CRYPTOFOLIO |
|
# http://cryptofolio.info/ - used for getting current BTC or $ estaminate |
|
CRYPTOFOLIO_ENABLED = true |
|
CRYPTOFOLIO_APIKEY = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX" |
|
CRYPTOFOLIO_TIMEOUT = 60 |
|
CRYPTOFOLIO_KEY = "BTC" # BTC / $ |
|
CRYPTOFOLIO_MONEYIN = 0.2 # money you put in, wether $ or BTC or 0 |
|
|
|
# CRYPTSY |
|
# https://www.cryptsy.com - trading plattform |
|
CRYPTSY_ENABLED = true |
|
CRYPTSY_PUBLICKEY = "PUBLIC KEY" |
|
CRYPTSY_PRIVATEKEY = "PRIVATE KEY" |
|
CRYPTSY_MARKETS = ["ANC/BTC"] # [] or ["WSC/BTC", 52, "XPM/LTC"] id or label |
|
CRYPTSY_HIDE_MARKETS = ["WDC/LTC"] # Hide markets we dont need (i dont trade WDC for LTC for example) |
|
CRYPTSY_SHOWBTC = true # show BTC markets where money is in |
|
CRYPTSY_SHOWLTC = true # show LTC markets where money is in |
|
CRYPTSY_SHOWXPM = false # show XPM markets where money is in |
|
CRYPTSY_CALC_PAYD = false # calculate how much you probably payd (DONT USE YET) |
|
CRYPTSY_TRADECOUNT = 200 # how many trades should be read for the buy price estermaniation |
|
CRYPTSY_TIMEOUT = 60 # How often to query to cryptsy data |
|
CRYPTSY_HTTP_TIMEOUT = 60 |
|
CRYPTSY_SHOWWIN = true # Show winnings on the end of the line |
|
CRYPTSY_BOUGHT = { |
|
"ZET/BTC" => 0.00008, |
|
"ADT/LTC" => 0.00000078, |
|
"WDC/BTC" => 0.00082, |
|
"SBC/BTC" => 0.00032, |
|
} |
|
|
|
## Colors & escapes |
|
|
|
BOLD = "\e[1m" |
|
DIM = "\e[2m" |
|
UNDERLINE = "\e[4m" |
|
BLINK = "\e[5m" |
|
INVERTED = "\e[7m" |
|
|
|
GREEN = "\e[92m" |
|
BLUE = "\e[94m" |
|
CYAN = "\e[36m" |
|
DGRAY = "\e[90m" |
|
GRAY = "\e[37m" |
|
MAGENTA = "\e[35m" |
|
WHITE = "\e[97m" |
|
RED = "\e[31m" |
|
|
|
B_GREEN = "\e[42m" |
|
B_RED = "\e[41m" |
|
B_CYAN = "\e[46m" |
|
|
|
CLEAR = "\e[0m" |
|
CLEARALL = "\033c" |
|
|
|
VERSION = "0.1.2" |
|
|
|
$start = Time.now |
|
$running = true |
|
$data = {} |
|
$draw_count = 0 |
|
|
|
$round = "1" |
|
(DECIMAL_LEN-1).times do |i| |
|
$round += "0" |
|
end |
|
$round = $round.to_i |
|
|
|
## Functions |
|
def _t; "#{CLEARALL}#{BOLD}#{WHITE}.:#{CYAN} Altcoin watcher #{WHITE}:. #{GRAY}#{VERSION}#{CLEAR}"; end |
|
def _l; "#{CLEAR}#{BOLD}#{WHITE}::#{CLEAR}#{GRAY} "; end |
|
def _r n; return (n*$round).round / $round.to_f; end |
|
def _rr n; return (n*1000).round / 1000.to_f; end |
|
def _rrr n; return (n*100).round / 100.to_f; end |
|
def _f v,l |
|
v = v.to_s |
|
if v.length < l |
|
return "#{v}#{" "*(l-v.length)}" |
|
elsif v.length > l |
|
return v.sub[0, l] |
|
else |
|
return v |
|
end |
|
end |
|
|
|
puts _t |
|
## |
|
# Cryptofolio.info |
|
# |
|
if CRYPTOFOLIO_ENABLED |
|
if CRYPTOFOLIO_KEY == "$" |
|
CRYPTOFOLIO__KEY = "@GrandTotal" |
|
else |
|
CRYPTOFOLIO__KEY = "@InBTCTotal" |
|
end |
|
$data[:cryptofolio] = { :last => 0 } |
|
end |
|
def get_cryptofolio |
|
if CRYPTOFOLIO_ENABLED |
|
value = open("http://www.cryptofolio.info/api/v1/?@UUID=#{CRYPTOFOLIO_APIKEY}&@VALUE=#{CRYPTOFOLIO__KEY}").read.to_f |
|
begin |
|
$data[:cryptofolio][:last] = $data[:cryptofolio][:value] if !$data[:cryptofolio][:value].nil? and $data[:cryptofolio][:last] != $data[:cryptofolio][:value] |
|
if value > $data[:cryptofolio][:last] and $data[:cryptofolio][:last] != 0 |
|
$data[:cryptofolio][:action] = :up |
|
elsif value < $data[:cryptofolio][:last] |
|
$data[:cryptofolio][:action] = :down |
|
elsif $data[:cryptofolio][:last] == 0 |
|
$data[:cryptofolio][:last] = value |
|
$data[:cryptofolio][:action] = nil |
|
end |
|
$data[:cryptofolio][:value] = value |
|
rescue Exception => e |
|
p e |
|
$data[:cryptofolio][:action] = :error |
|
end |
|
end |
|
end |
|
if CRYPTOFOLIO_ENABLED |
|
puts "#{_l}Cryptofolio #{GREEN}#{BOLD}enabled" |
|
get_cryptofolio |
|
puts "#{_l}Cryptofolio current value #{CYAN}#{_r($data[:cryptofolio][:value])}" |
|
puts "#{_l}Cryptofolio starting thread with Timeout of #{MAGENTA}#{CRYPTOFOLIO_TIMEOUT} seconds" |
|
Thread.new { |
|
while $running |
|
get_cryptofolio |
|
sleep CRYPTOFOLIO_TIMEOUT |
|
end |
|
} |
|
end |
|
|
|
## |
|
# Cryptsy |
|
# |
|
def cryptsy_index_balances |
|
status = Timeout::timeout(CRYPTSY_HTTP_TIMEOUT) { |
|
res = $cryptsy.getinfo['return'] |
|
if res.nil? or res['balances_available'].nil? |
|
puts "#{_l}Cryptsy #{RED}#{BOLD}error reading balances" |
|
else |
|
res['balances_available'].each do |k,m| |
|
if m.to_f > 0 |
|
$data[:cryptsy][:balances][k] = { :amount => m.to_f } |
|
end |
|
end |
|
res['balances_hold'].each do |k,m| |
|
if m.to_f > 0 |
|
if !$data[:cryptsy][:balances][k].nil? and $data[:cryptsy][:balances][k] > 0 |
|
$data[:cryptsy][:balances][k][:amount] += m.to_f |
|
else |
|
$data[:cryptsy][:balances][k] = { :amount => m.to_f } |
|
end |
|
end |
|
end |
|
end |
|
} |
|
end |
|
|
|
def cryptsy_index_markets |
|
status = Timeout::timeout(CRYPTSY_HTTP_TIMEOUT) { |
|
$cryptsy.getmarkets['return'].each do |m| |
|
market = m['label'].split("/") |
|
addmarket = false |
|
addmarket = true if CRYPTSY_MARKETS.include? m['label'] or CRYPTSY_MARKETS.include? m['marketid'].to_i |
|
addmarket = true if $data[:cryptsy][:balances].keys.include? market[0] |
|
addmarket = false if CRYPTSY_SHOWBTC == false && market[1] == "BTC" |
|
addmarket = false if CRYPTSY_SHOWLTC == false && market[1] == "LTC" |
|
addmarket = false if CRYPTSY_SHOWXPM == false && market[1] == "XPM" |
|
addmarket = false if CRYPTSY_HIDE_MARKETS.include? m['label'] or CRYPTSY_HIDE_MARKETS.include? m['marketid'].to_i |
|
lastt = m['last_trade'].to_f |
|
lastt = $data[:cryptsy][:markets][m['label']][:lastt] if !$data[:cryptsy][:markets][m['label']].nil? |
|
bought = 0 |
|
bought = $data[:cryptsy][:markets][m['label']][:bought] if !$data[:cryptsy][:markets][m['label']].nil? |
|
bought = CRYPTSY_BOUGHT[m['label']] if !CRYPTSY_BOUGHT[m['label']].nil? |
|
if addmarket |
|
$data[:cryptsy][:markets][m['label']] = { |
|
:id => m['marketid'].to_i, |
|
:volume => m['current_volume'].to_f, |
|
:last => m['last_trade'].to_f, |
|
:high => m['high_trade'].to_f, |
|
:low => m['low_trade'].to_f, |
|
:lastt => lastt, |
|
:bought => bought |
|
} |
|
end |
|
end |
|
} |
|
end |
|
def cryptsy_index_mytrades |
|
$data[:cryptsy][:markets].each do |k,m| |
|
market = k.split("/")[0] |
|
amount = $data[:cryptsy][:balances][market][:amount] |
|
payd = 0.0 |
|
status = Timeout::timeout(CRYPTSY_HTTP_TIMEOUT) { |
|
res = $cryptsy.mytrades(m['id'], CRYPTSY_TRADECOUNT) |
|
next if res["result"].nil? |
|
res["return"].each do |t| |
|
if t['tradetype'] == "Buy" |
|
payd += t['total'].to_f |
|
amount -= t['quantity'].to_f |
|
else |
|
amount += t['quantity'].to_f |
|
end |
|
break if amount <= 0 |
|
end |
|
} |
|
$data[:cryptsy][:markets][k][:bought] = payd/$data[:cryptsy][:balances][market][:amount] |
|
end |
|
end |
|
if CRYPTSY_ENABLED |
|
require 'cryptsy/api' |
|
puts "#{_l}Cryptsy #{GREEN}#{BOLD}enabled" |
|
$data[:cryptsy] = {} |
|
$data[:cryptsy][:balances] = {} |
|
$data[:cryptsy][:markets] = {} |
|
$cryptsy = Cryptsy::API::Client.new(CRYPTSY_PUBLICKEY, CRYPTSY_PRIVATEKEY) |
|
cryptsy_index_balances |
|
puts "#{_l}Cryptsy you have #{CYAN}#{BOLD}#{$data[:cryptsy][:balances].size}#{CLEAR}#{GRAY} different coins" |
|
cryptsy_index_markets |
|
puts "#{_l}Cryptsy indexing #{CYAN}#{BOLD}#{$data[:cryptsy][:markets].size}#{CLEAR}#{GRAY} markets" |
|
if CRYPTSY_CALC_PAYD |
|
print "#{_l}Cryptsy loading trading data, this may takes a while" |
|
cryptsy_index_mytrades |
|
print "\r#{_l}Cryptsy loading trading data, #{GREEN}#{BOLD}done#{CLEAR} \n" |
|
end |
|
end |
|
|
|
Thread.new { |
|
while $running |
|
begin |
|
cryptsy_index_balances |
|
sleep(CRYPTSY_TIMEOUT/2) |
|
cryptsy_index_markets |
|
sleep(CRYPTSY_TIMEOUT/2) |
|
rescue |
|
end |
|
end |
|
} |
|
|
|
|
|
## |
|
# Other functions |
|
# |
|
def relative_time(start_time) |
|
diff_seconds = Time.now - start_time |
|
case diff_seconds |
|
when 0 .. 59 |
|
return "#{_rrr(diff_seconds)} seconds" |
|
when 60 .. (3600-1) |
|
return "#{_rrr(diff_seconds/60)} minutes" |
|
when 3600 .. (3600*24-1) |
|
return "#{_rrr(diff_seconds/3600)} hours" |
|
when (3600*24) .. (3600*24*30) |
|
return "#{_rrr(diff_seconds/(3600*24))} days" |
|
else |
|
return start_time.strftime("%m/%d/%Y") |
|
end |
|
end |
|
|
|
## Actual code |
|
# set cursor \033[2;1H |
|
trap("INT") { $running = false } |
|
|
|
puts "#{_l}Starting screen loop..." |
|
sleep 1 |
|
cc = 0 |
|
puts "#{CLEARALL}" |
|
while $running |
|
begin |
|
if cc == 10 |
|
print "#{CLEARALL}" |
|
cc = 0 |
|
else |
|
print "\033[1;1H" |
|
end |
|
cc += 1 |
|
if CRYPTOFOLIO_ENABLED |
|
block = "#{B_CYAN} #{CLEAR}" |
|
diff = "#{CYAN}0%" |
|
if CRYPTOFOLIO_MONEYIN > 0 |
|
if $data[:cryptofolio][:value] > CRYPTOFOLIO_MONEYIN |
|
block = "#{B_GREEN} #{CLEAR}" |
|
diff = "#{GREEN}+#{_rr(($data[:cryptofolio][:value]/(CRYPTOFOLIO_MONEYIN/100))-100)}%" |
|
elsif $data[:cryptofolio][:value] < CRYPTOFOLIO_MONEYIN |
|
block = "#{B_RED} #{CLEAR}" |
|
diff = "#{RED}-#{_rr(CRYPTOFOLIO_MONEYIN/($data[:cryptofolio][:value]/100)-100)}%" |
|
end |
|
end |
|
change = "#{CYAN}?" |
|
change = "#{GREEN}^" if $data[:cryptofolio][:action] == :up |
|
change = "#{RED}v" if $data[:cryptofolio][:action] == :down |
|
puts "#{block}#{CLEAR} #{GRAY}Cryptofolio\t#{BOLD}#{change}#{CLEAR} #{WHITE}#{"%f#{DECIMAL_LEN+2}" % _r($data[:cryptofolio][:value])}\t#{diff}" |
|
end |
|
|
|
if CRYPTSY_ENABLED |
|
$data[:cryptsy][:markets].each do |k,m| |
|
block = "#{B_CYAN} #{CLEAR}" |
|
diff = "" |
|
win = "" |
|
#diff = "#{CYAN}0%" |
|
if $data[:cryptsy][:markets][k][:bought] == 0 |
|
block = "#{B_CYAN} #{CLEAR}" |
|
elsif $data[:cryptsy][:markets][k][:last] > $data[:cryptsy][:markets][k][:bought] |
|
block = "#{B_GREEN} #{CLEAR}" |
|
diff = "#{GREEN}+#{_f("%.3f" % _rr(($data[:cryptsy][:markets][k][:last]/($data[:cryptsy][:markets][k][:bought]/100))-100),6)}%" |
|
win = "#{MAGENTA}+#{"%.8f" % _r(($data[:cryptsy][:markets][k][:last]-$data[:cryptsy][:markets][k][:bought])*$data[:cryptsy][:balances][k.split("/")[0]][:amount])}" if CRYPTSY_SHOWWIN |
|
elsif $data[:cryptsy][:markets][k][:last] < $data[:cryptsy][:markets][k][:bought] |
|
block = "#{B_RED} #{CLEAR}" |
|
diff = "#{RED}-#{_f("%.3f" % _rr($data[:cryptsy][:markets][k][:bought]/($data[:cryptsy][:markets][k][:last]/100)-100),6)}%" |
|
win = "#{MAGENTA}-#{"%.8f" % _r(($data[:cryptsy][:markets][k][:bought]-$data[:cryptsy][:markets][k][:last])*$data[:cryptsy][:balances][k.split("/")[0]][:amount])}" if CRYPTSY_SHOWWIN |
|
end |
|
|
|
if CRYPTSY_SHOWWIN |
|
|
|
end |
|
|
|
change = "#{CYAN}?" |
|
change = "#{GREEN}^" if $data[:cryptsy][:markets][k][:lastt] < $data[:cryptsy][:markets][k][:last] |
|
change = "#{RED}v" if $data[:cryptsy][:markets][k][:lastt] > $data[:cryptsy][:markets][k][:last] |
|
change = "#{CYAN}?" if $data[:cryptsy][:markets][k][:lastt] == 0 || $data[:cryptsy][:markets][k][:lastt].nil? |
|
puts "#{block}#{CLEAR} #{GRAY}#{k}\t#{BOLD}#{change}#{CLEAR} #{WHITE}#{"%.8f" % _r(m[:last])}\t#{diff} #{win}" |
|
end |
|
end |
|
|
|
$draw_count += 1 |
|
puts "#{DGRAY} #{relative_time($start)} \t \t#{DGRAY}~#{$draw_count}" if TIMELINE |
|
|
|
sleep REDRAW_TIMEOUT |
|
rescue Exception => e |
|
puts "errr #{e}" |
|
sleep 10 |
|
end |
|
end |
|
|
|
puts "#{CLEARALL}#{BOLD}#{WHITE}Thanks for using #{GREEN}Altcoin watcher#{CLEAR}\n" |
|
puts "#{GRAY}Feel free to send some tips to my Cryptsy trade key:" |
|
puts "#{CYAN}26b13a60f5cd3aa78e4c29328fb9980bef963e9e\n" |
|
puts "#{CLEAR}#{GRAY}Altcoin watcher was running #{relative_time($start)}" |