Skip to content

Instantly share code, notes, and snippets.

@BransonGitomeh
Last active June 22, 2023 19:57
Show Gist options
  • Save BransonGitomeh/367436f77c3237cd5c8909eb8c3f4685 to your computer and use it in GitHub Desktop.
Save BransonGitomeh/367436f77c3237cd5c8909eb8c3f4685 to your computer and use it in GitHub Desktop.
Trading Bot for Managing Futures Positions This trading bot automates the process of opening and managing futures trading positions on Binance Futures. It allows you to profit from both rising and falling markets by leveraging futures contracts. Features: Automated position opening based on predefined symbols Continuous monitoring of Return on E…
BINANCE_API_KEY=
BINANCE_SECRET_KEY=
BINANCE_API_URL=https://fapi.binance.com
require('dotenv').config();
const axios = require('axios');
const Binance = require('node-binance-api');
// Extract necessary variables from environment
const { BINANCE_API_KEY, BINANCE_SECRET_KEY, NATS_URL } = process.env;
// Initialize Binance API client with authentication
const binance = new Binance().options({
APIKEY: BINANCE_API_KEY,
APISECRET: BINANCE_SECRET_KEY,
useServerTime: true,
recvWindow: 5000,
});
// Set binance object as global variable
global.binance = binance;
const assetInfoCache = {};
const getAssetInfo = async function (symbol) {
// Check if the response is already cached
if (assetInfoCache[symbol]) {
return Promise.resolve(assetInfoCache[symbol]);
}
try {
const response = await axios({
method: 'GET',
url: 'https://fapi.binance.com/fapi/v1/exchangeInfo',
});
const { symbols } = response.data;
const symbolInfo = symbols.find(s => s.symbol === symbol);
const { notional } = symbolInfo.filters.find(filter => {
return filter.filterType == 'MIN_NOTIONAL'
})
if (!symbolInfo.baseAssetPrecision) {
logger.info(symbolInfo);
}
// Store the response in the cache
assetInfoCache[symbol] = {
basePrecision: symbolInfo.baseAssetPrecision,
quotePrecision: symbolInfo.quotePrecision,
minNotional: Number(notional)
};
return Promise.resolve(assetInfoCache[symbol]);
} catch (error) {
console.error(`Error getting asset info: ${error}`);
throw error;
}
}
async function getCurrentPrice(symbol) {
return new Promise(async (resolve, reject) => {
try {
binance.futuresTickerStream(symbol, ticker => {
const currentPrice = parseFloat(ticker.close);
resolve(currentPrice)
});
} catch (error) {
console.error(`Error getting current price for symbol ${symbol}: ${error.message}`);
throw error;
}
})
}
const openOrder = async (symbol) => {
const assetInfo = await getAssetInfo(symbol);
const { basePrecision, quotePrecision, minNotional } = assetInfo;
const { availableBalance } = await global.binance.futuresAccount();
const riskPercentage = 0.2; // Risk 30% of available balance
const riskAmount = minNotional//availableBalance * riskPercentage; // Example risk amount
const leverage = 20; // Example leverage
const currentPrice = await getCurrentPrice(symbol)
let positionSize = Math.ceil(riskAmount / currentPrice);
const response = await global.binance.futuresSell(symbol, positionSize, undefined, {
leverage
});
return response
}
const reverseFailingPosition = async (position) => {
const { symbol } = position
const assetInfo = await getAssetInfo(symbol);
const { basePrecision, quotePrecision, minNotional } = assetInfo;
const { availableBalance } = await global.binance.futuresAccount();
const riskPercentage = 0.2; // Risk 30% of available balance
const riskAmount = minNotional//availableBalance * riskPercentage; // Example risk amount
const leverage = 20; // Example leverage
const currentPrice = await getCurrentPrice(symbol)
let positionSize = Math.ceil(riskAmount / currentPrice);
let response;
if (Number(position.positionAmt) > 0) {
response = await global.binance.futuresSell(symbol, positionSize * 2, undefined, {
leverage
});
} else {
response = await global.binance.futuresBuy(symbol, positionSize * 2, undefined, {
leverage
});
}
return response
}
const symbols = [
"IMXUSDT",
"XRPUSDT",
// "ETHUSDT",
// "BTCUSDT",
"DOGEUSDT",
"BALUSDT",
"EOSUSDT",
// "ETCUSDT",
"BATUSDT",
"BELUSDT",
// "BNBUSDT"
];
async function openOrdersSequentially(openPositions) {
for (const symbol of symbols) {
if (!openPositions.includes(symbol)) {
const response = await openOrder(symbol);
console.log(`Order for ${symbol}: ${JSON.stringify(response)}`);
}
}
}
function calculateROE(position) {
const entryPrice = parseFloat(position.entryPrice);
const markPrice = parseFloat(position.markPrice);
const positionAmt = parseFloat(position.positionAmt);
const leverage = parseFloat(position.leverage);
const unRealizedProfit = parseFloat(position.unRealizedProfit);
// Calculate the current value of the position
const currentValue = positionAmt * markPrice;
// Calculate the initial margin required for the position
const initialMargin = currentValue / leverage;
// Calculate the unrealized PnL of the position
const unrealizedPnl = parseFloat(position.unRealizedProfit);
// Calculate the return on equity (ROE)
const ROE = ((unrealizedPnl / initialMargin) * 100).toFixed(2);
if (unRealizedProfit > 0)
return Math.abs(ROE);
return -Math.abs(ROE);
}
const start = async () => {
const { serverTime: timestamp } = await binance.time();
const binanceGeneralPositions = await global.binance.futuresPositionRisk({ timestamp }) || [];
if (!binanceGeneralPositions[0]) {
console.error("Could not get access to Latest Positions data from binance.futuresPositionRisk")
return;
}
const openPositions = binanceGeneralPositions.filter(position => {
return Number(position.positionAmt) !== 0
})
const openPositionsSymbols = openPositions.map(position => position.symbol)
await openOrdersSequentially(openPositionsSymbols);
const positionData = []
for (const position of openPositions) {
try {
const binanceGeneralPositions = await global.binance.futuresPositionRisk({ timestamp }) || [];
const positionToMonitor = binanceGeneralPositions.find(generalPos => generalPos.symbol === position.symbol)
const ROE = await calculateROE(positionToMonitor)
const { symbol, unRealizedProfit, leverage } = position
positionData.push({
symbol,
uPNL: Number(unRealizedProfit).toFixed(2),
uPNLKes: Number(Number(unRealizedProfit) * 131).toFixed(2),
ROE,
leverage
})
if (ROE < -10) {
const attemptToFlipResponse = await reverseFailingPosition(positionToMonitor)
console.log("Successfully flipped position ", attemptToFlipResponse)
console.table(positionToMonitor)
}
} catch (error) {
console.log(error)
}
}
const sortedPositionData = positionData.sort((a, b) => a.ROE - b.ROE)
console.table(sortedPositionData)
start().catch(console.log)
}
start().catch(console.log)
@BransonGitomeh
Copy link
Author

BransonGitomeh commented Jun 22, 2023

Why Focus on Futures Contracts?

Futures contracts offer unique advantages that make them an attractive choice for maximizing returns:

  • Profit from Rising and Falling Markets: Unlike spot trading, futures contracts enable traders to profit from both upward and downward price movements. By taking long (buy) or short (sell) positions, the bot allows you to capitalize on opportunities in any market direction.

  • Leverage for Enhanced Returns: Binance Futures provides leverage, allowing traders to amplify their returns. By utilizing maximum leverage, the bot enables you to potentially achieve significant increases in return on equity (ROE) and capture opportunities for higher gains.

  • Minimum Positions and Risk Management: The bot incorporates the minimum position sizes enforced by Binance to ensure the lowest risk exposure per trade. This risk management approach protects against excessive losses and helps you maintain a balanced portfolio.


-. By leveraging the maximum available leverage, the bot aims to achieve amplified gains. The use of leverage allows you to potentially achieve ROEs of up to 1000%, which would be challenging and time-consuming to open manually.

-. The bot displays the position data, including the symbol, unrealized profit, ROE, and leverage. It sorts the positions based on ROE in ascending order, allowing you to quickly identify the positions that require attention and potential flipping.

-. The bot continues to monitor the positions, automatically flipping any position that falls below the -10% threshold. It provides real-time updates on the position data, helping you keep track of the performance and manage your portfolio effectively.

With the trading bot automating these tasks and utilizing futures contracts, you can easily get started with crypto portfolio management, maximize your returns, and effectively manage risk.

@BransonGitomeh
Copy link
Author

currently logs look like this

image

and the configurations of which markets to operate on can be changed in the code here

const symbols = [
    "IMXUSDT",
    "XRPUSDT",
    // "ETHUSDT",
    // "BTCUSDT",
    "DOGEUSDT",
    "BALUSDT",
    "EOSUSDT",
    // "ETCUSDT",
    "BATUSDT",
    "BELUSDT",
    // "BNBUSDT"
];

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment