June

Add trading_notice and lookup_order function & Modify trading logic & Add crypto buying condition

Showing 1 changed file with 314 additions and 84 deletions
......@@ -4,12 +4,17 @@ const express = require('express');
const app = express();
const { Coin } = require("./models/Coin");
const { User } = require('./models/User');
require("dotenv").config();
const fs = require('fs');
const path = require('path');
const HTTPS = require('https');
const domain = "2019102152.osschatbot.ga"
const sslport = 23023;
const TARGET_URL = 'https://api.line.me/v2/bot/message/reply'
const TOKEN = process.env.token;
var userid = process.env.userid;
const bodyParser = require('body-parser');
const crypto = require('crypto');
const queryEncode = require('querystring').encode;
......@@ -20,25 +25,23 @@ const access_key = process.env.access_key;
const secret_key = process.env.secret_key;
const server_url = "https://api.upbit.com"
var delay_count=1;
var krw_balance = 60000;
var divided_money = krw_balance / 10;
var krw_balance;
var divided_money;
var sort_info = new Array();
const mongoose = require('mongoose');
const config = require('./config/key');
app.use(bodyParser.json());
const connect = mongoose.connect(config.mongoURI, {
useNewUrlParser: true, useUnifiedTopology: true
})
.then(() => console.log('디비연결 성공'))
.catch((err) => console.log(err));
app.use(bodyParser.json());
var korean_name = new Object();
var korean_name = new Object();
function get_asset(market) {
const payload = {
......@@ -52,20 +55,61 @@ function get_asset(market) {
headers: { Authorization: `Bearer ${token}` },
}
const result = (market) => new Promise((resolve) => {
request(options, function (err, res, body) {
request(options, async function (err, res, body) {
if (err) throw new Error(err)
var empty = new Object();
data = JSON.parse(body);
if (market) {
data.filter(function (item) {
if (item.currency == market.split('-')[1]) {
// resolve(item);
empty.market = item;
} else if (item.currency == "KRW") {
empty.KRW = item
if (market == "asset") {
var current_asset = 0;
var pre_asset = 0;
for (var i = 0; i < data.length; i++) {
var candle;
if (data[i].currency == "KRW") {
current_asset += Number(data[i].balance);
pre_asset += Number(data[i].balance);
// hold_coin[data[i].currency]={volume:data[i].balance};
} else {
pre_asset += Number(data[i].balance * data[i].avg_buy_price)
candle = await get_candle(5, "KRW-" + data[i].currency);
current_asset += Number(candle[0].trade_price * data[i].balance);
// hold_coin[data[i].currency]={avg_buy_price:data[i].avg_buy_price,volume:data[i].balance,current_price:candle[0].trade_price};
}
}
resolve(empty);
})
resolve({ pre_asset: pre_asset.toFixed(0), current_asset: current_asset.toFixed(0), profit_data: (current_asset - pre_asset).toFixed(0), yield_data: ((current_asset - pre_asset) / pre_asset * 100).toFixed(2) });
} else if (market == "coin") {
var hold_coin = new Object();
for (var i = 0; i < data.length; i++) {
var candle;
if (data[i].currency == "KRW") {
hold_coin[data[i].currency] = { volume: Number(data[i].balance).toFixed(0).toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ",") };
} else {
candle = await get_candle(5, "KRW-" + data[i].currency);
var avg_buy_price = Number(data[i].avg_buy_price).toFixed(data[i].avg_buy_price < 1 ? 3 : 0)
var volume = Number(data[i].balance).toFixed(8);
var current_price = Number(candle[0].trade_price).toFixed(data[i].current_price < 1 ? 3 : 0);
var yield_data = (current_price - avg_buy_price) / avg_buy_price * 100;
yield_data = Number(yield_data).toFixed(2);
avg_buy_price = avg_buy_price.toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ",");
volume = volume.toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ",");
current_price = current_price.toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ",");
yield_data = yield_data.toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ",");
hold_coin[data[i].currency] = { avg_buy_price, volume, current_price, yield_data };
}
}
resolve(hold_coin);
} else {
data.filter(function (item) {
if (item.currency == market.split('-')[1]) {
// resolve(item);
empty.market = item;
} else if (item.currency == "KRW") {
empty.KRW = item
}
resolve(empty);
})
}
} else {
resolve(data);
}
......@@ -88,9 +132,8 @@ async function get_marketName() {
}
async function transaction_coin(coin_name, side, volume, price, ord_type, first = true) {
var volume = volume;
if (side == "ask") {
await User.findOne({ uid: 1 }).then((result) => {
console.log(result.volume);
if (side == "ask" && volume == "") {
await User.findOne({ market: coin_name }).then((result) => {
volume = String(result.volume);
}).catch(err => { console.log(err.error) });
}
......@@ -101,6 +144,7 @@ async function transaction_coin(coin_name, side, volume, price, ord_type, first
price: price,
ord_type: ord_type,
}
console.log(body);
//시장가 매수인 경우 price를 얼마치 살건지 입력
//시장가 매도인경우 volume에 몇개를 팔건지 입력
const query = queryEncode(body)
......@@ -126,6 +170,11 @@ async function transaction_coin(coin_name, side, volume, price, ord_type, first
}, delay)
})
var my_asset = await asset(1000);
if(my_asset.market&&my_asset.market.avg_buy_price){
lookup_order(result.uuid,my_asset.market.avg_buy_price);
}else{
lookup_order(result.uuid);
}
if (side == "bid") {
//처음 매수일 때
if (first) {
......@@ -133,28 +182,40 @@ async function transaction_coin(coin_name, side, volume, price, ord_type, first
await user.save().then(() => { isuser = true })
//2회 이상 매수일 때
} else {
User.findOneAndUpdate({uid:1},{krw_balance:my_asset.KRW.balance,avg_buy_price: my_asset.market.avg_buy_price, volume: my_asset.market.balance,$inc: { count: 1 }},{new :true},(err,result)=>{
if(err){
console.log(err);
}else{
console.log(result);
User.findOneAndUpdate({ uid: 1 }, { krw_balance: my_asset.KRW.balance, avg_buy_price: my_asset.market.avg_buy_price, volume: my_asset.market.balance, $inc: { count: 1 } }, { new: true }, (err, result) => {
if (err) {
// console.log(err);
} else {
// console.log(result);
}
})
}
} else if (side == "ask") {
//1회 매수 후 매도일 때
console.log("매도 쪽으로 진입");
if (first) {
User.deleteOne({ uid: 1 }, (err, res) => {
console.log("1회 매수 후 매도")
User.deleteOne({ market: coin_name }, (err, res) => {
if (err) {
console.log(err);
// console.log(err);
}
krw_balance = my_asset.KRW.balance;
divided_money = krw_balance / 10;
});
//분할 매수 분할 매도 중일 때
} else {
console.log("여러번 매수 후 매도");
User.findOneAndUpdate({ uid: 1 }, { krw_balance: my_asset.KRW.balance, avg_buy_price: my_asset.market.avg_buy_price, volume: my_asset.market.balance, count: 1 }, { new: true }, (err, result) => {
if (err) {
// console.log(err);
} else {
console.log(result);
}
})
}
}
}).catch((err) => { console.log(err.error) })
return;
}
async function get_marketInfo() {
//각 암호화폐 정보 조회
......@@ -191,7 +252,7 @@ async function save_coin(arr) {
});
await coin.save((err) => {
if (err) {
console.log(err)
// console.log(err)
}
})
}
......@@ -204,14 +265,15 @@ async function refresh_db() {
if (result.length !== 0) {
Coin.deleteMany({ tid: { $gt: 0 } }, (err, result) => {
if (err) {
console.log(err);
// console.log(err);
} else {
console.log(result);
// console.log(result);
}
})
}
save_coin(sort_info);
})
return;
}
async function get_candle(minute, market) {
const url = `https://api.upbit.com/v1/candles/minutes/${minute}?market=${market}&count=1`;
......@@ -221,79 +283,96 @@ async function get_candle(minute, market) {
.then(json => candle = json)
return candle;
}
async function price_comparison(candle, avg_buy_price = 0) {
var isbuying=true;
if (avg_buy_price == 0) {
async function price_comparison(candle, user_data = null, isbuying = false) {
//매수한 코인이 있을 때
var isbuying = isbuying;
if (user_data != null) {
console.log("매수 평균가 : " + user_data.avg_buy_price + ", 현재 가격 : " + candle[0].trade_price);
//매수평균가가 현재 시장 가격보다 더 비쌀 경우
var yield_data = (candle[0].trade_price - user_data.avg_buy_price) / user_data.avg_buy_price * 100;
if(yield_data<=-1){
// if (user_data.avg_buy_price > candle[0].trade_price) {
if (user_data.count < 9) {
transaction_coin(user_data.market, "bid", null, divided_money, "price", false)
} else if(user_data.count==9) {
transaction_coin(user_data.market, "bid", null, Math.floor(user_data.krw_balance-(user_data.krw_balance*0.001)), "price", false)
}
//매수평균가가 현재 시장 가격보다 더 쌀 경우
//수수료 포함 0.5% 이상 수익중일 때
} else if (yield_data >= 0.5) {
//매수 count가 1회이면서 수익률이 1.5프로 이상일때 시장가 전액 매도
if (user_data.count == 1 && yield_data >= 1.5) {
transaction_coin(user_data.market, "ask", user_data.volume, null, "market");
//전체 계좌 제산의 10프로를 제외한 나머지 코인을 매도
} else {
transaction_coin(user_data.market, "ask", (user_data.volume / user_data.count) * (user_data.count - 1), null, "market", false);
}
}
//매수한 코인이 없을 때
} else {
await Coin.findOne({ name: candle[0].market }).then(async (result) => {
//가격이 떨어졌을때
if (result.current_price > candle[0].trade_price) {
Coin.findOneAndUpdate({ name: candle[0].market }, { current_price: candle[0].trade_price, $inc: { count: 1 } }, { new: true }, (err, result) => {
if (err) {
console.log(err);
} else {
console.log("***" + result.korean_name + "은(는)" + result.count * 5 + "분 동안 하락중");
if (result.count >= 3) {
//해당 코인의 count를 +1 해준다
//해당 코인의 count가 3이상이면 upbit api로 매수 주문을 보낸다.
if (candle.length!=0 && result.length!=0) {
var yield_data = (candle[0].trade_price - result.current_price) / result.current_price * 100;
if (result.current_price > candle[0].trade_price) {
console.log("***" + result.korean_name + " " + candle[0].unit + "분 동안 " + yield_data.toFixed(2) + "% 하락");
await Coin.findOneAndUpdate({ name: candle[0].market }, { current_price: candle[0].trade_price, up_count: 0, $inc: { down_count: 1 } }, { new: true }).then(async (result) => {
if (isbuying == false && result.down_count >= 3&&result.name!="KRW-BTC") {
transaction_coin(result.name, "bid", null, divided_money, "price");
isbuying=false;
isbuying = true;
}
}
})
} else if (result.current_price < candle[0].trade_price) {
await Coin.findOneAndUpdate({ name: candle[0].market }, { current_price: candle[0].trade_price, count: 0 }, { new: true }).then(async (err, result) => {
if (err) {
console.log(err);
} else {
console.log(result.korean_name + "은(는)" + result.count * 5 + "분 동안 상승 혹은 정체중");
}
})
}).catch(err => { console.log(err) })
//가격이 상승했을때
//해당 코인의 count를 초기화한다.
} else if(result.current_price<candle[0].trade_price){
console.log(result.korean_name + " " + candle[0].unit + "분 동안" + yield_data.toFixed(2) + "% 상승");
await Coin.findOneAndUpdate({ name: candle[0].market }, { current_price: candle[0].trade_price, down_count: 0, $inc: { up_count: 1 } }, { new: true }).then(async (result) => {
}).catch(err => { console.log(err); })
}
}else{
console.log(촛불);
console.log(result);
}
})
} else {
if (avg_buy_price < candle[0].trade_price) {
transaction_coin(candle[0].market, "bid", null, divided_money, "price", false)
} else {
transaction_coin(candle[0].market, "ask", "", null, "market", false);
}
}
return isbuying;
}
async function check_coin(t1) {
User.find().then(async (user_data) => {
//아직 매수한 코인이 없을 때
if (user_data.length == 0) {
var isbuying = false;
for (var i = 0; i < t1.length; i++) {
if (isbuying) {
var candle = await get_candle(5, t1[i]);
isbuying=await price_comparison(candle);
console.log(isbuying);
}
}
//매수한 코인이 있을 때
} else {
//매수한 코인이 있을 때
var isbuying = user_data.length != 0 ? true : false;
if (isbuying) {
//3회 이상 매수 했을시 15분봉으로 교체해서 가격 확인
//15분봉 처리해야함
if (user_data[0].count > 3) {
var candle = await get_candle(15, user_data[0].market);
await price_comparison(candle, user_data[0].avg_buy_price);
if (user_data[0].count >= 3&&delay_count%3!=0&&user_data[0].count!=10) {
delay_count+=1;
} else {
delay_count=1;
var candle = await get_candle(5, user_data[0].market);
await price_comparison(candle, user_data[0].avg_buy_price);
await price_comparison(candle, user_data[0]);
}
}
//코인 count and 매수 매도 작업
for (var i = 0; i < t1.length; i++) {
if (user_data[0] && user_data[0].market == t1[i]) {
continue;
}
var candle = await get_candle(5, t1[i]);
isbuying = await price_comparison(candle, null, isbuying);
}
}).catch((err) => {
console.log(err);
})
return;
}
async function latest_repeat(t1) {
let check_time = setInterval(async () => {
let today = new Date();
let minutes = today.getMinutes();
let seconds = today.getSeconds();
// if (seconds == 0) {
if (minutes == 0 && seconds == 0) {
if (seconds == 0) {
// if (minutes == 0 && seconds == 0) {
clearInterval(check_time);
sort_info = (await sort_data());
(await refresh_db());
......@@ -309,32 +388,183 @@ async function latest_repeat(t1) {
let minutes = today.getMinutes();
let seconds = today.getSeconds();
console.log("현재 시간은 " + today.toLocaleTimeString());
await (check_coin(t1).then(count++));
//1시간마다 db 최신화...
if (count == 12) {
//24시간마다 db 최신화...
if (count == 12 * 24) {
count = 0;
sort_info = (await sort_data());
(await refresh_db());
console.log("db최신화");
} else {
await (check_coin(t1).then(count++));
}
}, 60000 * 5);
}
}, 1000);
}
function lookup_order(uuid,avg_buy_price=0) {
const body = {
uuid: uuid
}
const query = queryEncode(body)
const hash = crypto.createHash('sha512')
const queryHash = hash.update(query, 'utf-8').digest('hex')
const payload = {
access_key: access_key,
nonce: v4(),
query_hash: queryHash,
query_hash_alg: 'SHA512',
}
const token = sign(payload, secret_key)
const options = {
method: "GET",
url: server_url + "/v1/order?" + query,
headers: { Authorization: `Bearer ${token}` },
json: body
}
request(options, (error, response, body) => {
if (error) throw new Error(error)
var price = 0, volume = 0, funds = 0,yield_data=0;
var leng = body.trades.length;
for (var i = 0; i < leng; i++) {
price += body.trades[i].price;
volume += body.trades[i].volume;
funds += body.trades[i].funds;
}
price/=leng;
volume/=leng;
funds/=leng;
yield_data=((price-avg_buy_price)/avg_buy_price*100).toFixed(2).toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ",");
price = price.toFixed(price < 1 ? 3 : 0).toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ",");
volume = volume.toFixed(8).toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ",");
funds = funds.toFixed(0).toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ",");
if(avg_buy_price!=0){
trading_notice(body.side, price, funds, volume,yield_data);
}else{
trading_notice(body.side, price, funds, volume);
}
})
return;
}
function trading_notice(side, price, funds, volume,yield_data=0) {
var messages = new Array();
if (side == "bid") {
messages.push({ "type": "text", "text": "매수 주문이 체결되었습니다." });
messages.push({ "type": "text", "text": `체결 금액 : ${funds}원\n체결 수량 : ${volume}개\n체결 평균가 : ${price}원\n` });
} else {
messages.push({ "type": "text", "text": "매도 주문이 체결되었습니다." });
messages.push({ "type": "text", "text": `체결 금액 : ${funds}원\n체결 수량 : ${volume}개\n체결 평균가 : ${price}원\n수익률 : ${yield_data}%` });
}
var TARGET_URL = 'https://api.line.me/v2/bot/message/push';
request.post(
{
url: TARGET_URL,
headers: {
'Authorization': `Bearer ${TOKEN}`
},
json: {
"to": `${userid}`,
"messages": messages
}
}, (error, response, body) => {
});
return;
}
async function lookup_asset(replyToken) {
var result = await get_asset("asset");
request.post(
{
url: TARGET_URL,
headers: {
'Authorization': `Bearer ${TOKEN}`
},
json: {
"replyToken": replyToken,
"messages": [
{
"type": "text",
"text": `이전 자산 : ${result.pre_asset}`
},
{
"type": "text",
"text": `평가 자산 : ${result.current_asset}`
},
{
"type": "text",
"text": `평가 손익 : ${result.profit_data}, 수익률 : ${result.yield_data}%`
}
]
}
}, (error, response, body) => {
console.log(body)
});
return;
}
async function lookup_hold_coin(replyToken) {
var result = await get_asset("coin");
var messages = new Array();
var coin_list = Object.keys(result);
if (coin_list.length == 1) {
messages.push({ "type": "text", "text": "아직 보유중인 종목이 없습니다." });
} else {
for (var i = 0; i < coin_list.length; i++) {
if (coin_list[i] == "KRW") {
messages.push({ "type": "text", "text": `${coin_list[i]}\n사용 가능 원화 : ${result[coin_list[i]].volume}원` });
} else {
messages.push({
"type": "text",
"text": `${coin_list[i]}\n보유 수량 : ${(result[coin_list[i]].volume)}개\n매수 평균가 : ${result[coin_list[i]].avg_buy_price}원\n현재가 ${result[coin_list[i]].current_price}원\n수익률 : ${result[coin_list[i]].yield_data}%`
})
}
}
}
request.post(
{
url: TARGET_URL,
headers: {
'Authorization': `Bearer ${TOKEN}`
},
json: {
"replyToken": replyToken,
"messages": messages
}
}, (error, response, body) => {
console.log(body)
});
return;
}
app.post('/hook', function (req, res) {
var eventObj = req.body.events[0];
if (eventObj.message.text == "자산") {
lookup_asset(eventObj.replyToken)
} else if (eventObj.message.text == "보유 종목") {
lookup_hold_coin(eventObj.replyToken);
}
res.sendStatus(200);
});
try {
const option = {
ca: fs.readFileSync('/etc/letsencrypt/live/' + domain + '/fullchain.pem'),
key: fs.readFileSync(path.resolve(process.cwd(), '/etc/letsencrypt/live/' + domain + '/privkey.pem'), 'utf8').toString(),
cert: fs.readFileSync(path.resolve(process.cwd(), '/etc/letsencrypt/live/' + domain + '/cert.pem'), 'utf8').toString(),
};
HTTPS.createServer(option, app).listen(sslport, async () => {
console.log(`[HTTPS] Server is started on port ${sslport}`);
// console.log(await get_asset());
await get_asset().then((result) => {
krw_balance = result[0].balance;
divided_money = krw_balance / 10
});
var t1 = new Array();
await (latest_repeat(t1));
// console.log(await get_asset());
});
} catch (error) {
console.log('[HTTPS] HTTPS 오류가 발생하였습니다. HTTPS 서버는 실행되지 않습니다.');
console.log(error);
}
}
\ No newline at end of file
......