It was the Bitcointalk forum that inspired us to create Bitcointalksearch.org - Bitcointalk is an excellent site that should be the default page for anybody dealing in cryptocurrency, since it is a virtual gold-mine of data. However, our experience and user feedback led us create our site; Bitcointalk's search is slow, and difficult to get the results you need, because you need to log in first to find anything useful - furthermore, there are rate limiters for their search functionality.
The aim of our project is to create a faster website that yields more results and faster without having to create an account and eliminate the need to log in - your personal data, therefore, will never be in jeopardy since we are not asking for any of your data and you don't need to provide them to use our site with all of its capabilities.
We created this website with the sole purpose of users being able to search quickly and efficiently in the field of cryptocurrency so they will have access to the latest and most accurate information and thereby assisting the crypto-community at large.
#!/usr/bin/env python
# -*- mode: python; coding: utf-8 -*-
import sys
import os
import websocket
from sys import stdout, stderr
from datetime import datetime
MTGOX_WEBSOCKET_URI = 'ws://websocket.mtgox.com/mtgox'
GIMME_DEBUG = ('true', 't', 'yes', 'y', 'ja', 'j', '1')
def cb(ws, msg=None, fp=stdout):
if msg is not None:
log = '\t'.join([datetime.now().strftime('%F %T'), msg])
fp.write(log)
fp.write('\n')
fp.flush()
# end if
# end def cb
if os.environ.get('DEBUG', 'no').lower() in GIMME_DEBUG:
websocket.enableTrace(True)
else:
websocket.enableTrace(False)
# end if
if len(sys.argv) == 2:
wsuri = sys.argv[1]
else:
wsuri = MTGOX_WEBSOCKET_URI
# end if
ws = websocket.WebSocketApp(
wsuri,
on_open=lambda ws: cb(ws, 'opening %s' % wsuri, stderr),
on_close=lambda ws: cb(ws, 'closing %s' % wsuri, stderr),
on_message=cb,
on_error=lambda ws, msg=None: cb(ws, msg, stderr)
)
rc = 0
try:
ws.run_forever()
except (KeyboardInterrupt, SystemExit):
rc = 0
except Exception:
rc = 1
finally:
try:
ws.close()
except:
pass
# end if
# end if
sys.exit(rc)
# eof
$ ./ws-test
2011-06-28 22:38:16 opening ws://websocket.mtgox.com/mtgox
2011-06-28 22:38:16 {"channel":"dbf1dee9-4f2e-4a08-8cb7-748919a71b21","op":"subscribe"}
2011-06-28 22:38:16 {"channel":"d5f06780-30a8-4a48-a2f8-7ed181b4a13f","op":"subscribe"}
2011-06-28 22:38:16 {"channel":"24e67e0d-1cad-4cc0-9e7a-f8523ef460fe","op":"subscribe"}
^C
2011-06-28 22:38:21 closing ws://websocket.mtgox.com/mtgox
$
use Tk;
use JSON;
use LWP::Simple;
use Net::Telnet;
use strict;
#use warnings;
#todo
#ticker
#multiple markets
#min volume / increment filter
#scrolling the ladder
#options
#actual trading lol
my $pid = fork();
if($pid){
my ($ask,$bid,$price,%bidx,%askx,$lastprice);
my $fixprice = 0;
##TK Shiznet
my($change,$volume,$ordersize,$defaultordersize,$togglecenter);
my $mw = MainWindow->new;
$mw->optionAdd('*font', 'Helvetica 10');
$mw->title("BT Trader");
$mw->configure(-menu => my $menubar = $mw->Menu);
#menubar
my $filemb = $menubar->cascade(-label =>'File');
my $viewmb = $menubar->cascade(-label =>'View');
$filemb->command(
-label => 'Config',
-command => \&configure,
);
$filemb->command(
-label => 'Exit',
-command => sub {$mw->destroy();},
);
$viewmb->command(
-label => 'Time&Sales',
-command => \×ales,
);
$viewmb->command(
-label => 'Ticker',
-command => \&ticker,
);
my $leftside = $mw->Frame;
$leftside->Checkbutton(-text => "Fixed", -variable=>\$togglecenter,-font => ['Helvetica', '8', 'bold'])->pack(-side =>'top');
$leftside->pack(-side => 'left', -anchor => 'n');
#md ladder
my $ladder = $mw->Frame(-borderwidth=>2, -relief => 'groove');
for(my $i = 28; $i>0; $i--){
my($b,$p,$a);
$ladder->Button(-width => 2)->grid(
$b = $ladder->Button(-textvariable => \$bid->[$i], -background => 'DodgerBlue4', -foreground => 'white'),
$p = $ladder->Button(-textvariable => \$price->[$i], -background => 'snow4', -foreground => 'white'),
$a = $ladder->Button(-textvariable => \$ask->[$i], -background => 'red4', -foreground => 'white'),
$ladder->Button(-textvariable => \$lastprice->[$i], -width => 4),
-sticky => "nsew", -pady => 0
);
$b->configure(-command => [\&button_test, $b, $p ]);
$p->configure(-command => [\&button_test, $p, $p ]);
$a->configure(-command => [\&button_test, $a, $p ]);
#$ladder->Canvas(-background=>red, height=>1)->grid("-","-","-","-",-pady => 0);
}
$ladder->pack(-side=>'left');
$ladder->repeat(500, \&refresh);
sub button_test{
my ($var, $var2) = @_;
$var = $var->cget(-textvariable);
$var2= $var2->cget(-textvariable);
print("$$var $$var2\n");
}
#config window
my $cfg;
sub configure {
if (! Exists($cfg)) {
$cfg = $mw->Toplevel();
$cfg->title("Config");
}
else {
$cfg->deiconify( );
$cfg->raise( );
}
}
#time + sales
my ($tns,$tnsLB);
sub timesales{
if (! Exists($tns)) {
$tns = $mw->Toplevel();
$tns->title("Time&Sales");
$tnsLB = $tns->Listbox(-height => 30, -background => 'gray95', -relief => 'flat')->pack(-expand => 'y', -side=> 'left', -anchor => 'n');
}
else {
$tns->deiconify( );
$tns->raise( );
}
}
#ticker
my ($tkr,);
my @exchanges = ("MT Gox");
my (%thi, %tlo, %tla, %tby, %tsl, %tvol);
sub ticker{
if (! Exists($tkr)) {
$tkr = $mw->Toplevel();
$tkr->title("Ticker");
$tkr->Button(-text => "Exchange")->grid(
$tkr->Button(-text => "High"),
$tkr->Button(-text => "Low"),
$tkr->Button(-text => "Last"),
$tkr->Button(-text => "Bid"),
$tkr->Button(-text => "Ask"),
$tkr->Button(-text => "Volume"),
-sticky => "nsew");
foreach my $ex(@exchanges){
$tkr->Button(-text => "$ex")->grid(
$tkr->Button(-textvariable => \$thi{$ex}),
$tkr->Button(-textvariable => \$tlo{$ex}),
$tkr->Button(-textvariable => \$tla{$ex}),
$tkr->Button(-textvariable => \$tby{$ex}),
$tkr->Button(-textvariable => \$tsl{$ex}),
$tkr->Button(-textvariable => \$tvol{$ex}),
-sticky => "nsew");
}
}
else {
$tns->deiconify( );
$tns->raise( );
}
}
my $last;
sub refresh{
my($json,$json_txt,$json_ticker,$json_tl,$lastt);
#market data
open FILE, "md";
$json = JSON->new->utf8;
$json_txt = $json->decode();
close FILE;
#ticker
open FILE, "ticker";
$json_ticker = $json->decode();
close FILE;
$thi{"MT Gox"} = $json_ticker->{ticker}->{high};
$tlo{"MT Gox"} = $json_ticker->{ticker}->{low};
$tla{"MT Gox"} = $json_ticker->{ticker}->{last};
$tby{"MT Gox"} = $json_ticker->{ticker}->{buy};
$tsl{"MT Gox"} = $json_ticker->{ticker}->{sell};
$tvol{"MT Gox"}= $json_ticker->{ticker}->{vol};
#telnet feed
open FILE, "telnet_mtg";
my($lasttime,$lastvol,@lst);
#add time & sales
while(){
$json_tl = $json->decode( $_ );
if($lasttime != $json_tl->{timestamp} && Exists($tns) ){
print("$last $json_tl->{price}\n");
$lasttime = $json_tl->{volume}."@".$json_tl->{price};
$tnsLB->insert(0,$lasttime);
if($last > $json_tl->{price}){
$tnsLB->itemconfigure(0, -foreground => "red");
}
if($last < $json_tl->{price}){
$tnsLB->itemconfigure(0, -foreground => "green4");
}
$last = $json_tl->{price};
}
$lasttime = $json_tl->{timestamp};
$last = $json_tl->{price};
$lastvol = $json_tl->{volume};
}
close FILE;
if(Exists($tns)){
unlink("telnet_mtg");
}
#extract new data
my @newprice;
my %lp;
#cleanup
for (keys %askx){
delete $askx{$_};
}
for (keys %bidx){
delete $bidx{$_};
}
for (keys %lp){
delete $lp{$_};
}
#extract data from dom json dump
foreach my $item(@{$json_txt->{bids}}){
$bidx{ @{$item}->[0] } = @{$item}->[1];
push(@newprice,@{$item}->[0]);
}
foreach my $item(@{$json_txt->{asks}}){
$askx{ @{$item}->[0] } = @{$item}->[1];
push(@newprice,@{$item}->[0]);
}
@newprice = sort { $a <=> $b } @newprice;
#last
$lp{$last} = $lastvol;
#fill the arrays
my (@aska,@bida,@lpa);
my $x = 0;
foreach my $item(@newprice){
push(@bida,$bidx{$item}||"");
push(@aska,$askx{$item}||"");
push(@lpa,$lp{$item}||"");
}
#count offset + shift arrays
my $i = 0;
if($togglecenter || $fixprice == 0){
while($askx{$newprice[$i]} eq ""){
$i++;
}
$fixprice = $newprice[$i];
}
else{
while($newprice[$i]<$fixprice){
$i++;
}
}
my $toshift = $i-15;
for($i=0;$i<$toshift;$i++){
shift(@newprice);
shift(@aska);
shift(@bida);
shift(@lpa);
}
deep_copy(\@newprice,$price);
deep_copy(\@aska,$ask);
deep_copy(\@bida,$bid);
deep_copy(\@lpa,$lastprice);
}
sub deep_copy{
my ($src,$tgt)=@_;
if (ref $_[0] eq 'HASH'){copy_href(@_)}
elsif (ref $_[0] eq 'ARRAY'){copy_aref(@_)}
}
sub copy_href{
$_[1]||={};
for my $key (keys %{$_[0]}){
if (ref $_[0]->{$key}){
deep_copy($_[0]->{$key},$_[1]->{$key})
}
else {
$_[1]->{$key} = $_[0]->{$key}
}
}
}
sub copy_aref{
$_[1]||=[];
for my $i (0..$#{$_[0]}){
if (ref $_[0]->[$i]){
deep_copy($_[0]->[$i],$_[1]->[$i])
}
else {
$_[1]->[$i] = $_[0]->[$i]
}
}
}
MainLoop;
kill 1, $pid;
}
else{
$pid = fork;
if($pid){
while(1){
getstore("https://mtgox.com/code/data/getDepth.php","md");
getstore("https://mtgox.com/code/data/ticker.php","ticker");
sleep 1;
}
}
else{
my $t = new Net::Telnet(Host=>"bitcoincharts.com", Port=>27007, Timeout=>999);
my $line;
while(1){
$line = $t->getline();
if($line =~ /mtgoxUSD/){
open OUT, ">>telnet_mtg";
print OUT "$line";
close OUT;
}
sleep 1;
}
}
}