For making trading bots on top of CCXT, with simple lifecycle. In TypeScript.
Feel free to contribute.
{
keys: {
[key: string /* exchange */]: {
apiKey: string;
secret: string;
}
};
exchangesToWatch: string[];
orderBookLimit: number;
exchangeOptions: {
[key: string /* exchange */]: any
};
defaultExchangeOptions: any;
currenciesToWatch: string[];
makeOrders: boolean;
parallelOrders: boolean;
profile: boolean;
logDetails: boolean;
logAdditionalDetails: boolean;
logWarnings: boolean;
logAdditionalWarnings: boolean;
logError: boolean;
logErrorDetails: boolean;
// ccxt calculate_fees correction
feesRate: number;
zeroesFeesCorrection: boolean;
correctAllFees: boolean;
feesRoundType: 'ceil' | 'floor' |'round';
orderOptionsByExchange: {
[key: string /* exchange */]: any
};
defaultOrderOptions: any;
enableProxy: boolean;
changeProxyAfterEveryOrder: boolean;
changeProxyAfterAnyNetworkError: boolean;
proxies: string[];
telegram?: {
token: string;
startPhrase: string;
stopPhrase: string;
chats: string[];
logErrors: boolean;
}
}
import Bot from "arbitrage-algorithms-framework";
import { config, errorLogTemplate, log } from "arbitrage-algorithms-framework";
const bot = new Bot(config(require("path/to/config.local.json")));
const toIterate = [];
bot.init().then(
() => {
bot.printProfileTime();
bot.cycle(
toIterate,
(params) => {
// class extending Algorithm base class to be used in cycle
return new CustomAlgorithm(params)
}, iteratedElement => ({
// function for element adaptation
...iteratedElement
} as CustomAlgorithmParams),
() => {
log('Algorithm cycle stared');
bot.printProfileTime();
bot.telegram.sendMessage('Algorithm cycle stared');
}
);
},
err => log(errorLogTemplate(err))
);
Check src/example.ts
for more details.
- "fluid" fees (depends on fees.currency, other than default)
- use prepared error handler
- bot method for placing orders with retries
- WS adapter class compatible with ccxt (for updating iterating elements in rl time, making orders, use with proxy?)
- limits, precisions exceptions (per exchange, coin, exchange + coin and order side)
- make triangle orders at once via proxy or one by one
- fill order at once or chunk (depends on balance and/or agresivness)
- ArbitrageBetweenExchanges
- ArbitrageTriangularBetweenExchanges
- handle fees in BNB on binance
- handle other ordersand fees types (eg. oco, precision rounding types)
- ignore (exchange, market, coin) lists
- readme, docs
To start proxy on another server:
npm i arbitrage-algorithms-framework
npm i -g cors-anywhere
node node_modules/arbitrage-algorithms-framework/misc/proxy.js PORT HOST
Then add HOST:PORT in config proxies list.
MARKET: BASE/QUOTE
M0
/\
/ \
D0 |/_ \_
/ |\
_/ \
/| _\| D1
/ \
/____\____/____\
M2 / \ M1
D - DIRECTION,
M - MARKET,
C - COIN
M0 C0_C1
M1 C1_C2
M2 C0_C2
Direction 0:
M0 BUY (C0 for C1) | +C0 -C1
M1 BUY (C1 for C2) | +C1 -C2
M2 SELL (C0 for C2) | -C0 +C2
Direction 1:
M0 SELL (C0 for C1) | -C0 +C1
M1 SELL (C1 for C2) | -C1 +C2
M2 BUY (C0 for C2) | +C0 -C2
Temporary assumptions:
- don't use BNB for fees on Binance
- every exchange has limit orders
Known issues:
- handle minimum fees on Bleutrade
TBD
BUY C0 FOR C1 -> TRANSFER C0 -> SELL C0 FOR C1 -> TRANSFER C1 SELL C0 FOR C1 -> TRANSFER C1 -> BUY C0 FOR C1 -> TRANSFER C0
TBD
MARKET: BASE/QUOTE
M0E0
/\
/ \
|/_ \_
/ |\
_/ \
/| _\|
/ \
/____\____/____\
M2E1 / \ M1E0
D - DIRECTION,
M - MARKET,
C - COIN,
E - EXCHANGE
M0 C0_C1
M1 C1_C2
M2 C0_C2
Direction 0:
M0E0 BUY (C0 for C1) | +C0 -C1 | E0
M2E0 SELL (C0 for C2) | -C0 +C2 | E0
TRANSFER C2 FROM E0 TO E1 | -E0 +E1
M2E1 BUY (C0 for C2) | +C0 -C2 | E1
TRANSFER C0 FROM E1 TO E0 | -E1 +E0
Direction 1:
M0E0 SELL (C0 for C1) | -C0 +C1 | E0
M1E0 BUY (C2 for C1) | +C2 -C1 | E0
TRANSFER C2 FROM E0 TO E1 | -E0 +E1
M2E1 BUY (C0 for C2) | +C0 -C2 | E1
TRANSFER C0 FROM E1 TO E0 | -E1 +E0
Direction 2:
M0E0 BUY (C0 for C1) | +C0 -C1 | E0
TRANSFER C0 FROM E0 TO E1 | -E0 +E1
M2E1 SELL (C0 for C2) | -C0 +C2 | E1
M2E1 BUY (C0 for C2) | +C0 -C2 | E1
TRANSFER C0 FROM E1 TO E0 | -E1 +E0
Direction 3:
M0E0 SELL (C0 for C1) | -C0 +C1 | E0
TRANSFER C1 FROM E0 TO E1 | -E0 +E1
M1E1 BUY (C2 for C1) | +C2 -C1 | E1
M2E1 BUY (C0 for C2) | +C0 -C2 | E1
TRANSFER C0 FROM E1 TO E0 | -E1 +E0
Direction 4:
M0E0 BUY (C0 for C1) | +C0 -C1 | E0
TRANSFER C0 FROM E0 TO E1 | -E0 +E1
M2E1 SELL (C0 for C2) | -C0 +C2 | E1
M2E1 BUY (C0 for C2) | +C0 -C2 | E1
TRANSFER C0 FROM E1 TO E0 | -E1 +E0
Direction 5:
M0E0 SELL (C0 for C1) | -C0 +C1 | E0
TRANSFER C1 FROM E0 TO E1 | -E0 +E1
M1E1 BUY (C2 for C1) | +C2 -C1 | E1
M2E1 BUY (C0 for C2) | +C0 -C2 | E1
TRANSFER C0 FROM E1 TO E0 | -E1 +E0
Direction 0 is exemplary. Transfers can be between any cone, cones can be vary within three markets (not every occures in every direction).
m m m t t
m t t m m
t m m m t
m m t t m
t t m m m *
@TODO: GET EVERY POSSIBLE DIRECTION (* take into account bids/asks variation)