-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
197 additions
and
98 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
data | ||
node_modules/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"printWidth": 120, | ||
"tabWidth": 2, | ||
"singleQuote": true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"files.autoSave": "onFocusChange", | ||
"editor.tabSize": 2, | ||
"editor.fontSize": 12, | ||
"editor.rulers": [ | ||
120 | ||
], | ||
"[markdown]": { | ||
"editor.wordWrap": "off", | ||
"editor.quickSuggestions": false | ||
}, | ||
"editor.wordWrapColumn": 120 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
export default { | ||
HOST_MONGO: 'mongodb://localhost:27017', | ||
DB_NAME: 'crypto', | ||
TABLE_COIN: 'coins' | ||
COLLECTION_COIN: 'coins', | ||
COLLECTION_HISTORY: 'trade_history' | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,116 +1,139 @@ | ||
import request from 'request'; | ||
import request from 'request-promise-native'; | ||
import mongo from 'mongodb'; | ||
import Kraken from './providers/kraken'; | ||
import config from './config'; | ||
import BitTrex from './providers/bittrex'; | ||
|
||
const krakenApi = new Kraken('', '', {}); | ||
const MARKETS = []; | ||
|
||
const openDB = async () => { | ||
const client = await mongo.MongoClient.connect(config.HOST_MONGO); | ||
return client.db(config.DB_NAME); | ||
const client = await mongo.MongoClient.connect(config.HOST_MONGO); | ||
return client.db(config.DB_NAME); | ||
}; | ||
|
||
const getPriceTable = async (db) => { | ||
const collection = await db.collection(config.TABLE_COIN); | ||
const getHistoryCollectin = async db => { | ||
const collection = await db.collection(config.COLLECTION_HISTORY); | ||
return collection; | ||
}; | ||
|
||
const getUTCDate = () => { | ||
const d = new Date(); | ||
const leadingZero = (num) => `0${num}`.slice(-2); | ||
|
||
const formatTime = (date) => | ||
[date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds()] | ||
.map(leadingZero) | ||
.join(':'); | ||
|
||
return d.getUTCFullYear() + '-' + | ||
d.getUTCMonth() + '-' + | ||
d.getUTCDate() + ' ' + | ||
formatTime(d); | ||
const getPriceCollection = async db => { | ||
const collection = await db.collection(config.COLLECTION_COIN); | ||
collection.createIndex({ name: 1, market: 1 }, { unique: true }); | ||
return collection; | ||
}; | ||
|
||
|
||
|
||
|
||
|
||
const startTradingBot = async () => { | ||
const db = await openDB(); | ||
const table = await getPriceTable(db); | ||
|
||
const checkCoinPrice = async (collection, name, market) => { | ||
const coin = await collection.findOne({ name, market }); | ||
return coin; | ||
}; | ||
|
||
const checkCoinPrice = async (name, market) => { | ||
let {client, collection} = await openDB().catch(err => console.log('Error ', err)); | ||
let coin = await collection.findOne({name, market}); | ||
client.close(); | ||
return coin; | ||
const getStartPrice = async (collection, name, market) => { | ||
const coin = await collection.findOne({ name, market }); | ||
return coin.price_start; | ||
}; | ||
|
||
const updateCoinPrice = async ( | ||
collection, | ||
coin, | ||
priceMarket, | ||
priceStart, | ||
market, | ||
action | ||
) => { | ||
collection.update( | ||
{ | ||
name: coin, | ||
market: market | ||
}, | ||
{ | ||
name: coin, | ||
market: market, | ||
price_current: priceMarket, | ||
price_start: priceStart, | ||
action: action, | ||
time: new Date() | ||
}, | ||
{ | ||
upsert: true | ||
} | ||
); | ||
console.log('updateCoinPrice::done'); | ||
}; | ||
|
||
const updateCoinPrice = async (price, market, time) => { | ||
console.log('updateCoinPrice::', price, market); | ||
let {client, collection} = await openDB().catch(err => console.log('Error ', err)); | ||
collection.createIndex( { name: 1, market: 1 }, { unique: true } ); | ||
|
||
collection.update({ | ||
'name': 'BTC', | ||
'market': 'kraken' | ||
}, { | ||
'name': 'BTC', | ||
'market': market, | ||
'price': price, | ||
'time': time | ||
}, { | ||
upsert: true | ||
}); | ||
client.close(); | ||
console.log('updateCoinPrice::done'); | ||
const addToHistory = (coll, coin, price, market, action) => { | ||
coll.insert({ coin, price, market, action, time: new Date() }); | ||
}; | ||
|
||
const callKrakenApi = async () => { | ||
console.log('::callKrakenApi::'); | ||
const data = await krakenApi.api('Ticker', { pair : 'XXBTZEUR' }); | ||
const price = data.result['XXBTZEUR'].b[0]; | ||
const getPriceBittrex = async coinCode => { | ||
const bt = new BitTrex(request); | ||
const price = await bt.getPrice(coinCode); | ||
console.log('Price coins: ', price); | ||
}; | ||
|
||
updateCoinPrice(price, 'kraken', getUTCDate()).catch(err => { | ||
console.log('Cannot update price ', err); | ||
}); | ||
return price; | ||
const sellOnBittrex = async coinName => { | ||
console.log('sellOnBittrex::', coinName); | ||
}; | ||
|
||
const main = async() => { | ||
let coin = await checkCoinPrice('BTC', 'kraken'); | ||
let price = await callKrakenApi(); | ||
const buyOnBittrex = async coinName => { | ||
console.log('buyOnBittrex::', coinName); | ||
}; | ||
|
||
if(parseFloat(coin.price) < parseFloat(price)) { | ||
console.log('ALERT Price change up', coin.price, price); | ||
} else { | ||
console.log('No Price change', coin.price, price); | ||
const findNextAction = async (historyC, coin, market, percentChange) => { | ||
const last = await historyC.findOne( | ||
{ coin, market }, | ||
{ sort: { _id: -1 }, limit: 1 } | ||
); | ||
if (Math.abs(percentChange) > 10) { | ||
let nextActionBasedOnMarket = percentChange > 0 ? 'sell' : 'buy'; | ||
|
||
if ( | ||
(last.action === 'buy' && nextActionBasedOnMarket === 'sell') || | ||
(last.action === 'sell' && nextActionBasedOnMarket === 'buy') || | ||
!last.action | ||
) { | ||
return nextActionBasedOnMarket; | ||
} | ||
} | ||
return 'noaction'; | ||
}; | ||
|
||
main().catch(err => console.log('There is a general error', err)); | ||
|
||
// const websocket = new Gdax.WebsocketClient(['BTC-USD']); | ||
// websocket.on('message', data => { | ||
// console.log('Received data', data); | ||
// }); | ||
|
||
// const API_END_POINT = 'https://api.gdax.com'; | ||
|
||
// request('http://www.google.com', function(error, response, body) { | ||
// console.log('error:', error); // Print the error if one occurred | ||
// console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received | ||
// console.log('body:', body); // Print the HTML for the Google homepage. | ||
// }); | ||
const startTradingBot = async (coinName, market) => { | ||
console.log('startTradingBot::'); | ||
const db = await openDB(); | ||
const collection = await getPriceCollection(db); | ||
const historyColl = await getHistoryCollectin(db); | ||
let priceStart = await getStartPrice(collection, coinName, market); | ||
const priceMarket = await getPriceBittrex(coinName); | ||
|
||
if (!priceStart) priceStart = priceMarket; | ||
|
||
setInterval(async () => { | ||
console.log('checkingInterval::'); | ||
const percentChange = (priceMarket - priceStart) * 100 / priceMarket; | ||
const nextAction = await findNextAction( | ||
historyColl, | ||
coinName, | ||
market, | ||
percentChange | ||
); | ||
|
||
if (nextAction === 'sell') { | ||
const response = await sellOnBittrex(coinName); | ||
if (response.success) { | ||
sellOnBittrex(coinName); | ||
updateCoinPrice(collection, coinName, priceMarket, market); | ||
addToHistory(historyColl, coinName, price, market, nextAction); | ||
} | ||
} else if (nextAction === 'buy') { | ||
const response = await buyOnBittrex(coinName); | ||
if (response.success) { | ||
updateCoinPrice(collection, coinName, priceMarket, market); | ||
addToHistory(historyColl, coinName, price, market, nextAction); | ||
} | ||
} | ||
}, 30000); | ||
}; | ||
|
||
// const testURL = | ||
// 'https://bittrex.com/api/v1.1/public/getmarketsummary?market=btc-ltc'; | ||
// const bitTrexApi = 'https://bittrex.com/api/v1.1/{method}?param=value'; | ||
|
||
// request(testURL, function(error, response, body) { | ||
// let json = JSON.parse(body); | ||
// console.log('Value LTC in BTC is ', json.result[0].Last); | ||
// }); | ||
startTradingBot('LTC', 'bittrex').catch(e => console.log('error', e)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
export default class BitTrex { | ||
|
||
|
||
constructor(request) { | ||
this.request = request; | ||
this.apiPublic = 'https://bittrex.com/api/v1.1/public/'; | ||
this.baseCoin = 'USDT'; | ||
} | ||
|
||
async getCoinPrice(coinPair) { | ||
return await this.request.get({ | ||
url: this.apiPublic + 'getticker', | ||
qs: { | ||
market: coinPair | ||
}, | ||
json: true | ||
}); | ||
} | ||
|
||
async getMarket(coinPair) { | ||
return await this.request.get({ | ||
url: this.apiPublic + 'getmarketsummary', | ||
qs: { | ||
market: coinPair | ||
}, | ||
json: true | ||
}); | ||
} | ||
|
||
getBasePair(coin) { | ||
return `${this.baseCoin}-${coin}`; | ||
} | ||
|
||
async getPrice(coin) { | ||
const market = await this.getMarket(this.getBasePair(coin)); | ||
return market.result[0].Last; | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2102,6 +2102,10 @@ [email protected]: | |
version "2.4.1" | ||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-2.4.1.tgz#5b7723034dda4d262e5a46fb2c58d7cc22f71420" | ||
|
||
lodash@^4.13.1: | ||
version "4.17.5" | ||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511" | ||
|
||
lodash@^4.14.0, lodash@^4.17.4: | ||
version "4.17.4" | ||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" | ||
|
@@ -2680,6 +2684,20 @@ repeating@^2.0.0: | |
dependencies: | ||
is-finite "^1.0.0" | ||
|
||
[email protected]: | ||
version "1.1.1" | ||
resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.1.tgz#3eee00b2c5aa83239cfb04c5700da36f81cd08b6" | ||
dependencies: | ||
lodash "^4.13.1" | ||
|
||
request-promise-native@^1.0.5: | ||
version "1.0.5" | ||
resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.5.tgz#5281770f68e0c9719e5163fd3fab482215f4fda5" | ||
dependencies: | ||
request-promise-core "1.1.1" | ||
stealthy-require "^1.1.0" | ||
tough-cookie ">=2.3.3" | ||
|
||
[email protected]: | ||
version "2.74.0" | ||
resolved "https://registry.yarnpkg.com/request/-/request-2.74.0.tgz#7693ca768bbb0ea5c8ce08c084a45efa05b892ab" | ||
|
@@ -2931,6 +2949,10 @@ statuses@~1.3.1: | |
version "1.3.1" | ||
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" | ||
|
||
stealthy-require@^1.1.0: | ||
version "1.1.1" | ||
resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" | ||
|
||
stream-to-observable@^0.1.0: | ||
version "0.1.0" | ||
resolved "https://registry.yarnpkg.com/stream-to-observable/-/stream-to-observable-0.1.0.tgz#45bf1d9f2d7dc09bed81f1c307c430e68b84cffe" | ||
|
@@ -3026,6 +3048,12 @@ to-fast-properties@^1.0.3: | |
version "1.0.3" | ||
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" | ||
|
||
tough-cookie@>=2.3.3: | ||
version "2.3.4" | ||
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" | ||
dependencies: | ||
punycode "^1.4.1" | ||
|
||
tough-cookie@~2.3.0, tough-cookie@~2.3.3: | ||
version "2.3.3" | ||
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561" | ||
|