7 |
8 |
9 | This work is based on:
10 |
11 | - Gox Trading Bot (https://chrome.google.com/webstore/detail/gox-trading-bot/iejmifigokhpcgpmoacllcdiceicmejb)
12 | - Discussion thread (https://bitcointalk.org/index.php?topic=67591.0)
13 | - Base idea (https://bitcointalk.org/index.php?topic=60501)
14 |
15 | **The code was provided for educational/fun purposes and shouldn't be used to trade significant amounts of BTC!**
16 |
17 | Neither original author nor modifiers of the code are to be responsible for any damage caused by using this bot.
18 | There is no warranty of any kind that the source will perform according to any specification/expectations.
19 |
20 | **You as user are fully responsible for analysing the code and deciding if and how to use it.**
21 |
22 |
23 | Configuration:
24 | ---
25 |
26 | Constants in file background.js:
27 |
28 | **MaxHoursToKeep** - how many bars are kept in history to calculate EMA trends
29 |
30 | **btcPreserve** - amount of BTC that shouldn't be touched by trade (all amount above that will be used)
31 |
32 | **btcFiat** - replace with Your currency
33 |
34 | **bidWithLastPrice** - bid with last price rather than market price (poorly tested - for now effects in "dead" orders)
35 |
36 |
37 | Options to configure in run time:
38 |
39 | **MtGox API Key** - API key from MtGox
40 |
41 | **MtGox API Secret** - API secret from MtGox
42 |
43 | **EMAShort/EMALong** - EMA tick lengths
44 |
45 | **sellTreshold/buyTreshold** - sell/buy thresholds
46 |
47 | **Show last x days** - how many days of history to present
48 |
49 | **Enable Trading** - switch between trade and simulation mode
50 |
51 | **EMA Timeframe** - interval between ticks
52 |
53 | **Last Buy to Sell trigger** - difference in price to keep when selling BTC (comparing to wallet history)
54 |
55 | **Last Sell to Buy trigger** - same as above when buying BTC ("sold price" to "bought price" relation,"0" means no difference keeping)
56 |
57 |
58 |
59 | Installation:
60 | ---
61 |
62 | 1. Copy files from github to Your local storage.
63 | 2. Configure background.js according to above specs
64 | 3. Run Chrome and goto "chrome://extensions/" url
65 | 4. Click on (developer mode) "Read extension without package" and choose Your local folder
66 |
67 |
68 | Changes:
69 | ---
70 |
71 | 0.2.0.2
72 | - added chart with trends (a link from popup near balance)
73 | - added **hrInterval**
74 | - option to bid with last price rather than market price ()
75 | - different thresholds buy/sell
76 | - other minor fixes
77 |
78 | 0.2.0.3
79 | - hrInterval moved to dynamic (UI) options
80 | - "enableTrade" flag
81 | - minor layout fixes
82 |
83 | 0.2.0.4
84 | - added history data, gui fixes
85 |
86 | 0.2.0.5
87 | - added balance check using v1 api
88 | - added buy/sell difference keeper
89 | - other minor fixes
90 |
91 | Wanna feature? Donations:
92 | ---
93 | BTC:13eJdr8ndc3MJAeHGpVTNMPUtTGE8ANHpL
94 |
--------------------------------------------------------------------------------
/api/mtgox0.js:
--------------------------------------------------------------------------------
1 |
2 | function update() {
3 | mtgoxpost("info.php", [],
4 | function(e) {
5 | console.log("info error", e)
6 | chrome.browserAction.setTitle({title: "Error executing info" });
7 | schedupdate(10*1000) // retry after 10 seconds
8 | },
9 | function(d) {
10 | console.log("info.php", d.currentTarget.responseText)
11 | BTC = Number.NaN
12 | USD = Number.NaN
13 | try {
14 | var rr = JSON.parse(d.currentTarget.responseText)
15 | if (typeof(rr.Wallets[btcFiat].Balance.value)=="undefined") {
16 | chrome.browserAction.setTitle({title: rr.error });
17 | } else {
18 | BTC = parseFloat(rr.Wallets.BTC.Balance.value)
19 | USD = parseFloat(rr.Wallets[btcFiat].Balance.value)
20 | chrome.browserAction.setTitle({title: (rr.Wallets.BTC.Balance.value + " BTC + " + rr.Wallets[btcFiat].Balance.value + " " + btcFiat) });
21 | }
22 | } catch (e) {
23 | console.log(e)
24 | chrome.browserAction.setTitle({title: e.toString() });
25 | }
26 | schedupdate(5*60*1000) // Update balance every 5 minutes
27 | }
28 | )
29 | }
--------------------------------------------------------------------------------
/api/mtgox1.js:
--------------------------------------------------------------------------------
1 |
2 | function update() {
3 | mtgoxpost1("generic/private/info", [],
4 | function(e) {
5 | console.log("info error", e)
6 | chrome.browserAction.setTitle({title: "Error executing info" });
7 | schedupdate(10*1000) // retry after 10 seconds
8 | },
9 | function(d) {
10 | console.log("generic/private/info", d.currentTarget.responseText)
11 | BTC = Number.NaN
12 | USD = Number.NaN
13 | try {
14 | var rr = JSON.parse(d.currentTarget.responseText)
15 | if (rr.result == 'success') {
16 | rr = rr.return;
17 | if (typeof(rr.Wallets[btcFiat].Balance.value)=="undefined") {
18 | chrome.browserAction.setTitle({title: rr.error });
19 | } else {
20 | BTC = parseFloat(rr.Wallets.BTC.Balance.value)
21 | USD = parseFloat(rr.Wallets[btcFiat].Balance.value)
22 | chrome.browserAction.setTitle({title: (rr.Wallets.BTC.Balance.value + " BTC + " + rr.Wallets[btcFiat].Balance.value + " " + btcFiat) });
23 | }
24 | } else {
25 | console.log("info soft error", rr.error)
26 | chrome.browserAction.setTitle({title: "Error executing info:"+rr.error });
27 | //schedupdate(100*1000) // retry after 100 seconds
28 | }
29 | } catch (e) {
30 | console.log(e)
31 | chrome.browserAction.setTitle({title: e.toString() });
32 | }
33 | schedupdate(5*60*1000) // Update balance every 5 minutes
34 | }
35 | )
36 | }
--------------------------------------------------------------------------------
/background.js:
--------------------------------------------------------------------------------
1 | const MaxHoursToKeep = 144;
2 | const btcPreserve = 5; // this amount will be untouched by trade - bot will play with the rest
3 | const btcFiat = 'USD'; // change this to Your currency
4 | // const TimeFrame = 1800;// interval as number of seconds (ie 3600 - 1 hour)
5 | const bidWithLastPrice = false; // use last price to bid rather than market one
6 |
7 | var ApiKey = localStorage.ApiKey || '';
8 | var ApiSec = localStorage.ApiSec || '';
9 |
10 | var tradingEnabled = (localStorage.tradingEnabled || 1);
11 | var bsTrigSell = (localStorage.bsTrigSell || 0);
12 | var bsTrigBuy = (localStorage.bsTrigBuy || 0);
13 |
14 | var EmaShortPar = parseInt(localStorage.EmaShortPar || 10);
15 | var EmaLongPar = parseInt(localStorage.EmaLongPar || 21);
16 | var MaxHoursBack = parseInt(localStorage.MaxHoursBack || MaxHoursToKeep);
17 | var MinThresholdBuy = parseFloat(localStorage.MinThresholdBuy || 0.25);
18 | var MinThresholdSell = parseFloat(localStorage.MinThresholdSell || 0.25);
19 | var LogLines = parseInt(localStorage.LogLines || 12);
20 | var TimeFrame = parseInt(localStorage.TimeFrame || 3600);
21 |
22 | var BTC, USD;
23 | var utimer=null;
24 | var bootstrap = 1; // progress bar for loading initial H1 data from mtgox
25 |
26 | var H1 = []; // the H1 data
27 | var tim = [];
28 | var emaLong = [];
29 | var emaShort = [];
30 |
31 | var popupRefresh=null;
32 | var popupUpdateCounter=null;
33 | var updateinprogress=false;
34 |
35 |
36 | function updateEMA(ema, N) {
37 | var pr, k = 2 / (N+1);
38 | while (ema.length < H1.length) {
39 | if (ema.length==0) {
40 | ema.push(H1[0]);
41 | } else {
42 | ema.push( H1[ema.length] * k + ema[ema.length-1] * (1-k) )
43 | }
44 | }
45 | }
46 |
47 | function schedupdate(t) {
48 | if (utimer) clearTimeout()
49 | utimer = setTimeout(update,t)
50 | }
51 |
52 |
53 | function signdata(data) {
54 | var shaObj = new jsSHA(data, "ASCII")
55 | var SecretKey = atob(ApiSec)
56 | var hmac = shaObj.getHMAC(SecretKey, "ASCII", "SHA-512", "B64")
57 | while (hmac.length%4) hmac+='=' // workaround for the B64 too short bug
58 | return hmac
59 | }
60 |
61 |
62 | function mtgoxpost(page, params, ef, df) {
63 | var req = new XMLHttpRequest()
64 | req.open("POST", "https://mtgox.com/api/0/"+page, true)
65 | req.onerror = ef
66 | req.onload = df
67 | var data = "nonce="+((new Date()).getTime()*1000)
68 | for (var i in params) data += "&" + params[i]
69 | data = encodeURI(data)
70 | var hmac = signdata(data)
71 | req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
72 | req.setRequestHeader("Rest-Key", ApiKey)
73 | req.setRequestHeader("Rest-Sign", hmac)
74 | req.send(data)
75 | }
76 |
77 | function mtgoxpost1(page, params, ef, df) {
78 | var req = new XMLHttpRequest()
79 | req.open("POST", "https://mtgox.com/api/1/"+page, true)
80 | req.onerror = ef
81 | req.onload = df
82 | var data = "nonce="+((new Date()).getTime()*1000)
83 | for (var i in params) data += "&" + params[i]
84 | data = encodeURI(data)
85 | var hmac = signdata(data)
86 | req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
87 | req.setRequestHeader("Rest-Key", ApiKey)
88 | req.setRequestHeader("Rest-Sign", hmac)
89 | req.send(data)
90 | }
91 |
92 |
93 | function hmac_512(message) {
94 | var secret = atob(ApiSec);
95 | var shaObj = new jsSHA(message, "TEXT");
96 | var hmac = shaObj.getHMAC(secret, "B64", "SHA-512", "B64");
97 | return hmac
98 | }
99 |
100 | function mtgoxpost2(page, params, ef, df) {
101 | var req = new XMLHttpRequest()
102 | req.open("POST", "https://mtgox.com/api/2/"+page, true)
103 | req.onerror = ef
104 | req.onload = df
105 | var data = 'nonce='+((new Date()).getTime()*1000);
106 | for (var i in params) data += "&" + params[i];
107 | data = encodeURI(data);
108 | data = page + '\x00' + data;
109 | var hmac = hmac_512(data)
110 | //var hmac = signdata(data)
111 | req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
112 | req.setRequestHeader("Rest-Key", ApiKey)
113 | req.setRequestHeader("Rest-Sign", hmac)
114 | req.send(data)
115 | }
116 |
117 |
118 | function one(e) {
119 | console.log("ajax post error", e)
120 | }
121 |
122 | function onl(d) {
123 | console.log("ajax post ok", d)
124 | schedupdate(2500)
125 | }
126 |
127 |
128 | function dat2day(ms) {
129 | var t = new Date(ms)
130 | var y = t.getUTCFullYear().toString()
131 | var m = (t.getUTCMonth()+1).toString()
132 | var d = t.getUTCDate().toString()
133 | if (m.length<2) m='0'+m;
134 | if (d.length<2) d='0'+d;
135 | return y+"-"+m+"-"+d
136 | }
137 |
138 | function get_url(req, url) {
139 | //console.log(url)
140 | req.open("GET", url)
141 | req.send(null);
142 | }
143 |
144 |
145 | function getemadif(idx) {
146 | var cel = emaLong[idx]
147 | var ces = emaShort[idx]
148 | return 100 * (ces-cel) / ((ces+cel)/2)
149 | }
150 |
151 | function extractPrice(sfrom){
152 | var n=sfrom.indexOf("BTC at");
153 | n+=6;
154 | var ret = -1;
155 | var s2 = sfrom.substr(n);
156 | var s3 = "";
157 | for (var i=0; i| Price: | '+formatChartNumbers(data[1].y)+' |
| EMA'+bp.EmaShortPar+': | '+formatChartNumbers(data[0].y)+' |
| EMA'+bp.EmaLongPar+': | '+formatChartNumbers(data[2].y)+' |
|
31 | See chart.
32 |
33 | Read Goomboo's Journal
34 | to learn about the strategy used by this trading bot. 35 | The bot uses the first traded price of each hour for the EMA input. 36 | 37 | 38 | 39 | 122 |
123 | 1
124 | Take API Key and Secret from your MtGox account.
125 | Use Advanced API Key Creation at
126 | Security Center page
127 | to create these values.
128 | Make sure to grant only get_info and trade access rights for this API key.
129 | The bot does not need you to be logged at the MtGox account
130 | - just setup the Key&Secret, leave the browser running and it will trade...
131 |
140 |
141 | 132 | 2 133 | The bot will buy or sell all BTC above amount (preconfigured in file background.js) at the given MtGox account when the absolute difference between two EMA values (expressed in %) 134 | holds above the Threshold for the last one tick (hours). 135 | 136 | 3 137 | The bot will preserve loses by keeping last wallet state (not trading) in case buy/sell difference from last trade is less than given %. 138 | 0% means preserving loses is not active. 139 |
142 | original bot
143 |
144 |
145 | If You like modifications made from original bot
146 | send 0.01 BTC to
147 | 13eJdr8ndc3MJAeHGpVTNMPUtTGE8ANHpL
148 |
149 |
150 | If you like this extension send 0.01 BTC to
151 | 13g6zY7GJJvKEiYzTnGP8H9dEDEhYW2jFq
152 |
153 |
154 | |
| 17 | 18 | | 19 |||||
|---|---|---|---|---|
22 |
23 | |
24 | 25 | 26 | | 27 ||||
|
32 | Problem accessing MtGox account. 33 | Some chart. 34 | Go check the Options page. 35 | |
36 | ||||
41 |
42 | |
43 | 44 | Balance = 0.00 BTC + 0.00 45 | | 46 ||||
| Hour | Price | EMA(a) / EMA(b) 51 | | ||