Skip to content

Commit

Permalink
Adjusting how "orders/done" operation works by taking the orders from…
Browse files Browse the repository at this point in the history
… sheets with the "orders/table" operations in them.
  • Loading branch information
diegomanuel committed Feb 14, 2021
1 parent 32eab0a commit 935c779
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 126 deletions.
3 changes: 0 additions & 3 deletions BINANCE.gs
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,6 @@ function BINANCE(operation, range_or_cell, opts, force_refresh_cell) {
if (BinDoOrdersTable().is(operation)) {
return BinDoOrdersTable().run(range_or_cell, options);
}
if (BinDoOrdersTableStats().is(operation)) {
return BinDoOrdersTableStats().run(range_or_cell, options);
}

throw new Error("Unsupported operation given: '"+operation+"'");
}
Expand Down
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ By using the `BINANCE()` formula in your spreadsheet, you can get data fetched f
* Last [24h stats](#operation-stats24h-public)
* Total [account assets](#operation-account-private) from Binance wallets (SPOT + CROSS + ISOLATED for now)
* All current [open orders](#operation-ordersopen-private) (SPOT + CROSS + ISOLATED for now)
* Latest [done/finished orders](#operation-ordersdone-private) (SPOT for now)
* Historical [orders table + stats](#operation-orderstable-private) (SPOT + CROSS + ISOLATED for now)
* Latest [done/finished orders](#operation-ordersdone-private) (SPOT + CROSS + ISOLATED for now)
* Historical [orders table](#operation-orderstable-private) (SPOT + CROSS + ISOLATED for now)
* Last data [update time](#operation-last_update-public) and current [add-on version](#operation-version-public) being used
* ..and many more to come!

Expand Down Expand Up @@ -136,13 +136,6 @@ Some operations are **private**, meaning they **do require a Binance API key** t
* `=BINANCE("orders/open", "BTCUSDT")` Optionally you can give a **full ticker** to filter the results.
* `=BINANCE("orders/open", "BTCUSDT", "headers: false")` Optionally you can give more options like not returning table headers.

### Operation: `"orders/done"` (private)
`=BINANCE("orders/done", A1:A3)` will return a list with your most recent (`10` per symbol by default) done/finished orders for given symbols from Binance.
* A single value like `"BTC"` or a range of values is **required**. Values must be simple symbols like `A1="BTC"`, `A2="ETH"` and `A3="LTC"`.
* `=BINANCE("orders/done", A1:A3, "BTC")` Optionally you can give a ticker to match against (defaults to `USDT`).
* `=BINANCE("orders/done", A1:A3, "ticker: BTC, headers: false, max: 100")` Optionally you can give more options like not returning table headers and fetching latest `100` orders per given symbol.
* Values for `max` allowed between `1` and `1000` (defaults to `10`).

### Operation: `"orders/table"` (private)
`=BINANCE("orders/table", MySheet!A1:A3)` will **transform** the current sheet into a **"table"** in where ALL historic done/finished orders will be periodically polled and stored for each given symbol from Binance (SPOT + CROSS + ISOLATED for now).
* This formula **must always** be placed at `A1` in any new blank sheet into your spreadsheet.
Expand Down Expand Up @@ -170,8 +163,15 @@ Some operations are **private**, meaning they **do require a Binance API key** t
But if you have _MANY_ trading symbols, I don't know how well it could behave!
The best option is to try to "merge" as much as you can in a single sheet with JUST the traded symbols for each one.

### Operation: `"orders/table/stats"` (private)
`=BINANCE("orders/table/stats", 'Orders Table'!A1)` _coming soon_
### Operation: `"orders/done"` (private)
**IMPORTANT:** It now requires at least **ONE sheet** in the spreadsheet with the **`"orders/table"`** operation in it!
It will take **ALL** your sheets that have the **`"orders/table"`** operation (aka: "order table sheets") and it will summarize them for you in a single table.
* `=BINANCE("orders/done")` Will return a list with your most recent (`100` by default) done/finished orders from ALL `"orders/table"` sheets in the spreadsheet.
<!-- * A single value like `"BTC"` or a range of values is **required**. Values must be simple symbols like `A1="BTC"`, `A2="ETH"` and `A3="LTC"`.
* `=BINANCE("orders/done", A1:A3, "BTC")` Optionally you can give a ticker to match against (defaults to `USDT`).
* `=BINANCE("orders/done", A1:A3, "ticker: BTC, headers: false, max: 0")` Optionally you can give more options like giving a ticker, not returning table headers and displaying ALL orders. -->
* `=BINANCE("orders/done", "", "headers: false, max: 0")` Optionally you can give more options like not returning table headers and displaying ALL orders.
* Values for `max` allowed between `0` (unlimited/all) and `1000` (defaults to `100`).

## See it working live!

Expand Down
4 changes: 1 addition & 3 deletions tasks/do-account-info.gs
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,8 @@ function BinDoAccountInfo() {
}

function parseOverview(show_headers) {
const wallet = BinWallet();
const headers = ["Asset", "Free", "Locked", "Borrowed", "Interest", "Total", "Net"];

const assets = wallet.calculateAssets();
const assets = BinWallet().calculateAssets();
const balances = Object.keys(assets).map(function (symbol) {
const asset = assets[symbol];
return [
Expand Down
84 changes: 31 additions & 53 deletions tasks/do-orders-done.gs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@
* Runs the done orders script.
*/
function BinDoOrdersDone() {
const max_items = 10; // How many items to be fetched for each symbol by default
const delay = 250; // Delay between API calls in milliseconds
let lock_retries = 5; // Max retries to acquire lock
const max_items = 100; // How many items to be displayed by default

/**
* Returns this function tag (the one that's used for BINANCE function 1st parameter)
Expand All @@ -28,10 +26,12 @@ function BinDoOrdersDone() {
}

/**
* Returns the most recent filled/done orders for given symbols (10 per symbol by default).
* Returns the most recent filled/done orders (100 by default) from ALL sheets that are "order tables" in the spreadsheet
* NOTE: It requires at least ONE sheet with the 'orders/table' operation in it!
* @TODO Add support to filter by `range_or_cell` and/or `ticker` option!
*
* @param {["BTC","ETH"..]} range_or_cell REQUIRED! Will fetch recent done orders for given symbols only.
* @param options Ticker to match against (USDT by default) or an option list like "ticker: USDT, headers: false, max: 100"
* @param {["BTC","ETH"..]} range_or_cell Will fetch recent done orders for given symbols only.
* @param options Ticker to match against (USDT by default) or an option list like "ticker: USDT, headers: false, max: 0"
* @return The list of all current done orders for all or given symbols/tickers.
*/
function run(range_or_cell, options) {
Expand All @@ -45,65 +45,43 @@ function BinDoOrdersDone() {
}
}

// @TODO Implement `range_or_cell` and/or `ticker` filtering
function execute(range_or_cell, options) {
const ticker_against = options["ticker"];
const limit = _getMaxItems(options); // Get max items limit
// const ticker_against = options["ticker"];
Logger.log("[BinDoOrdersDone] Running..");
if (!range_or_cell) {
throw new Error("A range with crypto names must be given!");
}
const lock = BinUtils().getUserLock(lock_retries--);
if (!lock) { // Could not acquire lock! => Retry
return execute(range_or_cell, options);
}

const range = BinUtils().getRangeOrCell(range_or_cell) || [];
const opts = {
CACHE_TTL: 55,
"retries": range.length
};
const data = range.reduce(function(rows, crypto) {
const qs = "limit="+limit+"&symbol="+crypto+ticker_against;
Utilities.sleep(delay); // Add some waiting time to avoid 418 responses!
const crypto_data = BinRequest(opts).get("api/v3/myTrades", qs, "");
return rows.concat(crypto_data);
}, []);

BinUtils().releaseLock(lock);
// const range = BinUtils().getRangeOrCell(range_or_cell) || [];
// const data = range.reduce(function(rows, asset) {
// return rows.concat(asset);
// }, []);
// const parsed = parse(data, options);

// Get ALL the rows contained in ALL defined sheets as order tables!
const data = BinDoOrdersTable().getRows();
if (!data.length) {
console.error("[BinDoOrdersDone] It seems that we didn't find any sheet in the spreadsheet with the 'orders/table' operation in it!");
return [["- no results to display - WARNING: This operation requires at least ONE sheet in the spreadsheet with the 'orders/table' operation in it!"]];
}
const parsed = parse(data, options);
Logger.log("[BinDoOrdersDone] Returning "+data.length+" orders..");
Logger.log("[BinDoOrdersDone] Done!");
return parsed;
}

function parse(data, options) {
const header = ["#ID", "Date", "Pair", "Type", "Side", "Price", "Amount", "Commission", "Total"];
const parsed = data.reduce(function(rows, order) {
const price = BinUtils().parsePrice(order.price);
const amount = parseFloat(order.qty);
const commission = BinUtils().parsePrice(order.commission);
const row = [
order.orderId,
new Date(parseInt(order.time)),
order.symbol,
order.isMaker ? "LIMIT" : "STOP-LIMIT",
order.isBuyer ? "BUY" : "SELL",
price,
amount,
commission,
price*amount
];
rows.push(row);
return rows;
}, []);

const sorted = BinUtils().sortResults(parsed, 1, true);
const header = ["Order #ID", "Date", "Pair", "Type", "Side", "Price", "Amount", "Commission", "Total"];
const parsed = data.map(function(order) {
order.shift(); // Remove the first column (Trade #ID)
return order;
});
let sorted = BinUtils().sortResults(parsed, 1, true);
const limit = parseInt(options["max"]||max_items); // Max items to display
if (limit > 0 && limit < sorted.length) {
sorted = sorted.slice(0, limit);
}
return BinUtils().parseBool(options["headers"]) ? [header, ...sorted] : sorted;
}

function _getMaxItems(options) {
return Math.max(1, Math.min(1000, parseInt(options["max"]||max_items))); // Cap between 1 and 1000 items per symbol
}

// Return just what's needed from outside!
return {
tag,
Expand Down
46 changes: 0 additions & 46 deletions tasks/do-orders-table-stats.gs

This file was deleted.

29 changes: 23 additions & 6 deletions tasks/do-orders-table.gs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ function BinDoOrdersTable() {
* You may ONLY REMOVE records from the bottom of the sheet (as many as you want, even all of them).
*
* @param {["BTC","ETH"..]} range_or_cell REQUIRED! Will fetch ALL historic orders for given symbols only.
* @param options Ticker to match against (USDT by default) or an option list like "ticker: USDT, stats: false"
* @TODO Implement "stats: false" option
* @param options Ticker to match against (USDT by default) or an option list like "ticker: USDT"
* @return The list of all orders for all or given symbols/tickers.
*/
function run(range_or_cell, options) {
Expand Down Expand Up @@ -263,7 +262,7 @@ function BinDoOrdersTable() {
sheet.getRange("E2:F2").mergeAcross();

// Set the table headers
const header = ["#ID", "Order #ID", "Date", "Pair", "Type", "Side", "Price", "Amount", "Commission", "Total"];
const header = ["Trade #ID", "Order #ID", "Date", "Pair", "Type", "Side", "Price", "Amount", "Commission", "Total"];
sheet.getRange("A3:J3").setValues([header]);
sheet.getRange("A2").setValue("Last poll:");
sheet.getRange("D2").setValue("Status:");
Expand Down Expand Up @@ -392,8 +391,8 @@ function BinDoOrdersTable() {
const range = sheet.getRange(last_row+1, 1, dlen, last_col);
range.setValues(data);

// Sort ALL sheet rows!
sheet.getRange(header_size+1, 1, sheet.getLastRow()-header_size, last_col).sort(3);
// Sort ALL sheet's rows!
_getSheetDataRange(sheet).sort(3);
}

function _setStatus(sheet, status) {
Expand Down Expand Up @@ -441,13 +440,31 @@ function BinDoOrdersTable() {
return PropertiesService.getScriptProperties().setProperty(ASSETS_PROP_NAME, JSON.stringify(updated_assets));
}

/**
* Get the FULL data range for given sheet
*/
function _getSheetDataRange(sheet) {
return sheet.getRange(header_size+1, 1, sheet.getLastRow()-header_size, sheet.getLastColumn());
}

/**
* Returns ALL the rows contained in ALL defined sheets as order tables
*/
function getRows() {
return _findSheets().reduce(function(rows, sheet) { // Go through each sheet found
const values = _getSheetDataRange(sheet).getValues();
return values && values.length ? rows.concat(values) : rows;
}, []);
}

// Return just what's needed from outside!
return {
tag,
is,
period,
run,
init,
execute
execute,
getRows
};
}
8 changes: 4 additions & 4 deletions ui/setup.gs
Original file line number Diff line number Diff line change
Expand Up @@ -167,14 +167,14 @@ function BinSetup() {

if (!api_key) {
ui.alert("Binance API Key is not set!",
"You just need a Binance API Key if you want open/done orders list.\n\n"+
"It's NOT needed to get market prices and 24hr stats!",
"You just need a Binance API Key if you want to use private operations.\n\n"+
"It's NOT needed to use public operations like current market prices and 24hr stats!",
ui.ButtonSet.OK);
}
if (!api_secret) {
ui.alert("Binance API Secret Key is not set!",
"You just need a Binance API Secret Key if you want open/done orders.\n\n"+
"It's NOT needed to get market prices and 24hr stats!",
"You just need a Binance API Secret Key if you to use private operations.\n\n"+
"It's NOT needed to use public operations like current market prices and 24hr stats!",
ui.ButtonSet.OK);
}
}
Expand Down

0 comments on commit 935c779

Please sign in to comment.