Skip to content

Commit

Permalink
Merge pull request #9 from eugeneglova/refactoring
Browse files Browse the repository at this point in the history
Refactoring
  • Loading branch information
eugeneglova committed Nov 29, 2020
2 parents 10941a1 + 9093443 commit 78b62e3
Show file tree
Hide file tree
Showing 6 changed files with 371 additions and 72 deletions.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "binance-trading-bot",
"version": "1.1.7",
"version": "1.1.8",
"description": "Binance Trading Bot",
"main": "src/electron/electron.js",
"homepage": "./",
Expand Down
207 changes: 149 additions & 58 deletions src/components/Trading/Trading.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useState, useEffect } from 'react'
import { Button, Table, Space, Collapse } from 'antd'
import { Button, Table, Space, Collapse, List, Dropdown, Menu } from 'antd'
import { ipcRenderer } from 'electron'
import Store from 'electron-store'

Expand All @@ -23,9 +23,15 @@ const precision = (value, decimals = getDecimals(value)) =>
const getPLPerc = (basePrice, price, sideSign) => ((price / basePrice - 1) / sideSign) * 100

const Trading = ({
isRunning = [], onStart, onStop,
onConnect, onDisconnect, isWSConnected,
onStartTelegramBot, onStopTelegramBot, isTelegramBotStarted,
isRunning = [],
onStart,
onStop,
onConnect,
onDisconnect,
isWSConnected,
onStartTelegramBot,
onStopTelegramBot,
isTelegramBotStarted,
}) => {
const store = new Store()
const config = store.get()
Expand Down Expand Up @@ -99,6 +105,61 @@ const Trading = ({
},
]

const getMenu = (index, action) => (
<Menu>
<Menu.Item>
<Button
size="small"
onClick={() => {
ipcRenderer.send(action, index, 10)
}}
>
10%
</Button>
</Menu.Item>
<Menu.Item>
<Button
size="small"
onClick={() => {
ipcRenderer.send(action, index, 25)
}}
>
25%
</Button>
</Menu.Item>
<Menu.Item>
<Button
size="small"
onClick={() => {
ipcRenderer.send(action, index, 50)
}}
>
50%
</Button>
</Menu.Item>
<Menu.Item>
<Button
size="small"
onClick={() => {
ipcRenderer.send(action, index, 75)
}}
>
75%
</Button>
</Menu.Item>
<Menu.Item>
<Button
size="small"
onClick={() => {
ipcRenderer.send(action, index, 100)
}}
>
100%
</Button>
</Menu.Item>
</Menu>
)

return (
<div>
<div>
Expand Down Expand Up @@ -163,62 +224,92 @@ const Trading = ({
</Space>
</div>

<List
itemLayout="horizontal"
dataSource={config.POSITIONS}
renderItem={(pos, index) => (
<List.Item>
<List.Item.Meta
title={
<Space>
{pos.SYMBOL} {pos.SIDE}
<Button
type="primary"
size="small"
onClick={() => {
onStart(index)
}}
disabled={isRunning[index]}
loading={!!isRunning[index]}
>
Start
</Button>
<Button
type="primary"
size="small"
onClick={() => {
onStop(index)
}}
disabled={!isRunning[index]}
danger
>
Stop
</Button>
<Button
type="primary"
size="small"
onClick={() => {
onStop(index)
onStart(index)
}}
disabled={!isRunning[index]}
>
Restart
</Button>
</Space>
}
description={
<Space>
<Button
type="primary"
size="small"
onClick={() => {
ipcRenderer.send('cancelOrders', index)
}}
>
Cancel Orders
</Button>
<Dropdown overlay={getMenu(index, 'addStopOrder')} placement="bottomRight">
<Button
type="primary"
size="small"
onClick={() => {
ipcRenderer.send('addStopOrder', index)
}}
>
Add Stop Without Loss
</Button>
</Dropdown>
<Dropdown overlay={getMenu(index, 'takeProfitOrder')} placement="bottomRight">
<Button
type="primary"
size="small"
onClick={() => {
ipcRenderer.send('takeProfitOrder', index)
}}
>
Take Profit
</Button>
</Dropdown>
</Space>
}
/>
</List.Item>
)}
/>

{config.POSITIONS.map((pos, index) => (
<div>
<Space>
<span>{pos.SYMBOL}</span>
<span>{pos.SIDE}</span>
<Button
type="primary"
size="small"
onClick={() => {
onStart(index)
}}
disabled={isRunning[index]}
>
Start
</Button>
<Button
type="primary"
size="small"
onClick={() => {
onStop(index)
}}
disabled={!isRunning[index]}
>
Stop
</Button>
<Button
type="primary"
size="small"
onClick={() => {
onStop(index)
onStart(index)
}}
disabled={!isRunning[index]}
>
Restart
</Button>
<Button
type="primary"
size="small"
onClick={() => {
ipcRenderer.send('cancelOrders', index)
}}
>
Cancel Orders
</Button>
<Button
type="primary"
size="small"
onClick={() => {
ipcRenderer.send('addStopOrder', index)
}}
>
Add Stop Without Loss
</Button>
</Space>

{false && isRunning[index] && (
<div>
{botState[index] && botState[index].position && (
Expand Down
89 changes: 85 additions & 4 deletions src/electron/bot.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ const {
getPosSize,
} = require('./functions')

let exchangeInfo
const getCachedExchangeInfo = async (binance) => {
if (exchangeInfo) {
return exchangeInfo
}
exchangeInfo = await binance.futures.exchangeInfo()
return exchangeInfo
}

const start = async (em, index, contents) => {
const store = new Store()
let config = store.get().POSITIONS[index]
Expand Down Expand Up @@ -662,7 +671,7 @@ const start = async (em, index, contents) => {

// start
await binance.useServerTime()
const info = await binance.futures.exchangeInfo()
const info = await getCachedExchangeInfo(binance)
const { pricePrecision, quantityPrecision } = info.symbols.find(
(item) => item.symbol === config.SYMBOL,
)
Expand Down Expand Up @@ -860,7 +869,7 @@ const cancelOrders = async (index) => {
cancelOpenOrders()
}

const addStopOrder = async (index) => {
const addStopOrder = async (index, percent = 100) => {
const store = new Store()
let config = store.get().POSITIONS[index]

Expand All @@ -872,6 +881,10 @@ const addStopOrder = async (index) => {
})

await binance.useServerTime()
const info = await getCachedExchangeInfo(binance)
const { pricePrecision, quantityPrecision } = info.symbols.find(
(item) => item.symbol === config.SYMBOL,
)
const positions = await binance.futures
.positionRisk()
.catch((e) => console.error(new Error().stack) || console.error(e))
Expand All @@ -892,11 +905,12 @@ const addStopOrder = async (index) => {

const SIDE_SIGN = p.positionSide === 'SHORT' ? -1 : 1

const spPrice = precision(getPLPrice(parseFloat(p.entryPrice), 0.05, SIDE_SIGN))
const spPrice = precision(getPLPrice(parseFloat(p.entryPrice), 0.05, SIDE_SIGN), pricePrecision)
const amount = precision(Math.abs((parseFloat(p.positionAmt) * percent) / 100), quantityPrecision)

await binance.futures[SIDE_SIGN < 0 ? 'stopMarketBuy' : 'stopMarketSell'](
config.SYMBOL,
Math.abs(parseFloat(p.positionAmt)),
amount,
spPrice,
{
positionSide: p.positionSide,
Expand All @@ -909,9 +923,76 @@ const addStopOrder = async (index) => {
)
}

const takeProfitOrder = async (index, percent = 100) => {
const store = new Store()
let config = store.get().POSITIONS[index]

const binance = Binance({
APIKEY: store.get().APIKEY,
APISECRET: store.get().APISECRET,
useServerTime: true,
recvWindow: 15000,
})

await binance.useServerTime()
const info = await getCachedExchangeInfo(binance)
const { pricePrecision, quantityPrecision } = info.symbols.find(
(item) => item.symbol === config.SYMBOL,
)
const positions = await binance.futures
.positionRisk()
.catch((e) => console.error(new Error().stack) || console.error(e))
if (!positions) {
console.error('ERROR: check positions')
return
}

const p = _.find(
positions,
({ symbol, positionSide, positionAmt }) =>
symbol === config.SYMBOL &&
(config.SIDE === 'AUTO' ? true : positionSide === config.SIDE) &&
parseFloat(positionAmt) !== 0,
)

if (!p) return

const SIDE_SIGN = p.positionSide === 'SHORT' ? -1 : 1

const quote = await binance.futures
.quote(config.SYMBOL)
.catch(
(e) =>
console.log(config.SYMBOL, config.SIDE) ||
console.error(new Error().stack) ||
console.error(e),
)
const minTakeProfitPrice =
SIDE_SIGN > 0
? Math.max(parseFloat(p.entryPrice), parseFloat(quote.askPrice))
: Math.min(parseFloat(p.entryPrice), parseFloat(quote.bidPrice))

const price = precision(
getNextPrice(minTakeProfitPrice, 0, -SIDE_SIGN, [{ PRICE_STEP: config.PRICE_DISTANCE }]),
pricePrecision,
)

const amount = precision(Math.abs((parseFloat(p.positionAmt) * percent) / 100), quantityPrecision)

await binance.futures[SIDE_SIGN < 0 ? 'buy' : 'sell'](config.SYMBOL, amount, price, {
positionSide: p.positionSide,
}).catch(
(e) =>
console.log(config.SYMBOL, config.SIDE) ||
console.error(new Error().stack) ||
console.error(e),
)
}

module.exports = {
start,
connect,
cancelOrders,
addStopOrder,
takeProfitOrder,
}
Loading

0 comments on commit 78b62e3

Please sign in to comment.