Bitcoin Forum
December 11, 2016, 01:50:59 PM *
News: To be able to use the next phase of the beta forum software, please ensure that your email address is correct/functional.
 
   Home   Help Search Donate Login Register  
Pages: [1]
  Print  
Author Topic: BT TRADER - MD Trader clone for Linux and Windows  (Read 4743 times)
dutt
Member
**
Offline Offline

Activity: 111



View Profile
June 28, 2011, 08:20:13 PM
 #1

Screenshot:


This is a clone of MD TRADER in perl/tk.
I don't have any trading functionality implemented as of yet, because I don't have enough bitcoins to deposit to MtGox.
So if you want me to continue develop send me bitcoins until I reach 1 BTC on the address below. Or you could just implement it yourself, which should be easy if you know perl.

If you have windows you need activeperl first, and maybe install some packages through the package manager, but I'm not sure actually, I developed and tested it on windows ONLY but I don't know which packages aren't vanilla activeperl.

Please leave a comment.

Oh and it uses the bitcoincharts telnet stream for time+sales instead of websockets because port 80 is blocked by my isp Sad

Code:
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 => \&timesales,
);
$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( <FILE> );
        close FILE;
        
        #ticker
        open FILE, "ticker";
        $json_ticker = $json->decode( <FILE> );
        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(<FILE> ){

            $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;
        }
        
    }
}

1481464259
Hero Member
*
Offline Offline

Posts: 1481464259

View Profile Personal Message (Offline)

Ignore
1481464259
Reply with quote  #2

1481464259
Report to moderator
1481464259
Hero Member
*
Offline Offline

Posts: 1481464259

View Profile Personal Message (Offline)

Ignore
1481464259
Reply with quote  #2

1481464259
Report to moderator
1481464259
Hero Member
*
Offline Offline

Posts: 1481464259

View Profile Personal Message (Offline)

Ignore
1481464259
Reply with quote  #2

1481464259
Report to moderator
Advertised sites are not endorsed by the Bitcoin Forum. They may be unsafe, untrustworthy, or illegal in your jurisdiction. Advertise here.
1481464259
Hero Member
*
Offline Offline

Posts: 1481464259

View Profile Personal Message (Offline)

Ignore
1481464259
Reply with quote  #2

1481464259
Report to moderator
1481464259
Hero Member
*
Offline Offline

Posts: 1481464259

View Profile Personal Message (Offline)

Ignore
1481464259
Reply with quote  #2

1481464259
Report to moderator
kseistrup
Hero Member
*****
Offline Offline

Activity: 565


Unselfish actions pay back better


View Profile WWW
June 28, 2011, 08:32:16 PM
 #2


it uses the bitcoincharts telnet stream for time+sales instead of websockets because port 80 is blocked by my isp Sad

You mean that your ISP block ingoing traffic to port 80?  But only the outgoing traffic is to port 80, ingoing traffic cannot be to port 80 — at least not on Linux (unless you're root, which you shouldn't be in this case).

Cheers,

Klaus Alexander Seistrup
http://about.me/kseistrup
dutt
Member
**
Offline Offline

Activity: 111



View Profile
June 28, 2011, 08:33:42 PM
 #3

Not sure, thing is that I can't connect to the mtgox websocket  Undecided

kseistrup
Hero Member
*****
Offline Offline

Activity: 565


Unselfish actions pay back better


View Profile WWW
June 28, 2011, 08:39:51 PM
 #4


Not sure, thing is that I can't connect to the mtgox websocket  Undecided

Mt. Gox' websockets are non-functional at the moment, could that be why?

This is an extremely simple websocket client that connects to Mt. Gox unless you give it another url:

Code:
#!/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

and all I get at the moment is this:

Code:
$ ./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
$

Cheers,

Klaus Alexander Seistrup
http://about.me/kseistrup
dutt
Member
**
Offline Offline

Activity: 111



View Profile
June 28, 2011, 10:55:20 PM
 #5

Quote
2011-06-28 23:53:33     closing ws://websocket.mtgox.com/mtgox
This is all I get.

kseistrup
Hero Member
*****
Offline Offline

Activity: 565


Unselfish actions pay back better


View Profile WWW
June 29, 2011, 07:46:45 AM
 #6

That's very weird, I have no idea what's happening here…

Klaus Alexander Seistrup
http://about.me/kseistrup
Pages: [1]
  Print  
 
Jump to:  

Sponsored by , a Bitcoin-accepting VPN.
Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!