117 files changed
+10768
-4762
No files matched your search
@@ -35,3 +35,4 @@ PATH_TO_WEB_SERVER=./BackendServers/
|
||||
|
||||
APP_SCHEMA_PATH=./
|
||||
WORKSPACE_PATH=./
|
||||
MY_WORKSPACES_PATH=./My-Workspaces
|
||||
+74
-7
@@ -432,6 +432,12 @@
|
||||
"compatibleTypes": "->Shapes->"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"name": "polygonCondition",
|
||||
"type": "node",
|
||||
"childType": "Polygon Condition",
|
||||
"autoAdd": true
|
||||
},
|
||||
{
|
||||
"name": "polygonBody",
|
||||
"type": "node",
|
||||
@@ -452,6 +458,14 @@
|
||||
}
|
||||
],
|
||||
"menuItems": [
|
||||
{
|
||||
"action": "Add UI Object",
|
||||
"disableIfPropertyIsDefined": true,
|
||||
"propertyToCheckFor": "polygonCondition",
|
||||
"actionFunction": "payload.onMenuItemClick",
|
||||
"label": "Add Polygon Condition",
|
||||
"relatedUiObject": "Polygon Condition"
|
||||
},
|
||||
{
|
||||
"action": "Add UI Object",
|
||||
"disableIfPropertyIsDefined": true,
|
||||
@@ -486,6 +500,41 @@
|
||||
],
|
||||
"addLeftIcons": true
|
||||
},
|
||||
{
|
||||
"type": "Polygon Condition",
|
||||
"icon": "style-condition",
|
||||
"level": 4,
|
||||
"propertyNameAtParent": "polygonCondition",
|
||||
"chainAttachesTo": {
|
||||
"compatibleTypes": "->Polygon->"
|
||||
},
|
||||
"editors": {
|
||||
"code": true
|
||||
},
|
||||
"initialValues": {
|
||||
"code": ""
|
||||
},
|
||||
"properties": [],
|
||||
"menuItems": [
|
||||
{
|
||||
"action": "Edit Condition",
|
||||
"actionFunction": "uiObject.codeEditor.activate",
|
||||
"label": "Edit Condition",
|
||||
"iconPathOn": "html",
|
||||
"iconPathOff": "html"
|
||||
},
|
||||
{
|
||||
"action": "Delete UI Object",
|
||||
"askConfirmation": true,
|
||||
"confirmationLabel": "Confirm to Delete",
|
||||
"actionFunction": "payload.onMenuItemClick",
|
||||
"label": "Delete Style Condition",
|
||||
"iconPathOn": "delete",
|
||||
"iconPathOff": "delete"
|
||||
}
|
||||
],
|
||||
"addLeftIcons": true
|
||||
},
|
||||
{
|
||||
"type": "Polygon Body",
|
||||
"docURL": "https://docs.superalgos.org/suite-hierarchy-data-mine.html#polygon-body",
|
||||
@@ -805,12 +854,30 @@
|
||||
"type": "Condition",
|
||||
"docURL": "https://docs.superalgos.org/suite-hierarchy-trading-system.html#condition",
|
||||
"menuItems": [
|
||||
{
|
||||
"action": "Edit Condition",
|
||||
"actionFunction": "uiObject.conditionEditor.activate",
|
||||
"label": "Edit Condition",
|
||||
"relatedUiObject": "Condition"
|
||||
},
|
||||
{
|
||||
"action": "Add UI Object",
|
||||
"disableIfPropertyIsDefined": true,
|
||||
"propertyToCheckFor": "javascriptCode",
|
||||
"label": "Add Code",
|
||||
"relatedUiObject": "Condition",
|
||||
"relatedUiObject": "Javascript Code",
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
},
|
||||
{
|
||||
"action": "Fetch Code to Javascript Code",
|
||||
"label": "Fetch from Javascript Code",
|
||||
"relatedUiObject": "Javascript Code",
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
},
|
||||
{
|
||||
"action": "Push Code to Javascript Code",
|
||||
"label": "Push to Javascript Code",
|
||||
"relatedUiObject": "Javascript Code",
|
||||
"actionFunction": "payload.onMenuItemClick"
|
||||
},
|
||||
{
|
||||
@@ -1756,7 +1823,7 @@
|
||||
},
|
||||
{
|
||||
"type": "Parameters",
|
||||
"docURL": "https://docs.superalgos.org/suite-hierarchy-trading-system.html#parameters",
|
||||
"docURL": "https://docs.superalgos.org/suite-hierarchy-network.html#parameters",
|
||||
"menuItems": [
|
||||
{
|
||||
"action": "Add Missing Children",
|
||||
@@ -1822,7 +1889,7 @@
|
||||
},
|
||||
{
|
||||
"type": "Base Asset",
|
||||
"docURL": "https://docs.superalgos.org/suite-hierarchy-trading-system.html#base-asset",
|
||||
"docURL": "https://docs.superalgos.org/suite-hierarchy-network.html#base-asset",
|
||||
"menuItems": [
|
||||
{
|
||||
"action": "Configure Base Asset",
|
||||
@@ -2012,7 +2079,7 @@
|
||||
},
|
||||
{
|
||||
"type": "Time Range",
|
||||
"docURL": "https://docs.superalgos.org/suite-hierarchy-trading-system.html#time-range",
|
||||
"docURL": "https://docs.superalgos.org/suite-hierarchy-network.html#time-range",
|
||||
"menuItems": [
|
||||
{
|
||||
"action": "Configure Time Range",
|
||||
@@ -2047,7 +2114,7 @@
|
||||
},
|
||||
{
|
||||
"type": "Time Frame",
|
||||
"docURL": "https://docs.superalgos.org/suite-hierarchy-trading-system.html#time-frame",
|
||||
"docURL": "https://docs.superalgos.org/suite-hierarchy-network.html#time-frame",
|
||||
"menuItems": [
|
||||
{
|
||||
"action": "Configure Time Frame",
|
||||
@@ -2082,7 +2149,7 @@
|
||||
},
|
||||
{
|
||||
"type": "Slippage",
|
||||
"docURL": "https://docs.superalgos.org/suite-hierarchy-trading-system.html#slippage",
|
||||
"docURL": "https://docs.superalgos.org/suite-hierarchy-network.html#slippage",
|
||||
"menuItems": [
|
||||
{
|
||||
"action": "Configure Slippage",
|
||||
@@ -2117,7 +2184,7 @@
|
||||
},
|
||||
{
|
||||
"type": "Fee Structure",
|
||||
"docURL": "https://docs.superalgos.org/suite-hierarchy-trading-system.html#fee-structure",
|
||||
"docURL": "https://docs.superalgos.org/suite-hierarchy-network.html#fee-structure",
|
||||
"menuItems": [
|
||||
{
|
||||
"action": "Configure Fee Structure",
|
||||
|
||||
@@ -63,8 +63,9 @@ function newAppLoader() {
|
||||
'Panels/PlotterPanel.js',
|
||||
'Panels/PanelsVisibleButton.js',
|
||||
|
||||
'ControlsToolBox/SidePanel.js',
|
||||
'ControlsToolBox/SidePanelTab.js',
|
||||
'SideSpace/SidePanelTab.js',
|
||||
'SideSpace/ListView.js',
|
||||
'SideSpace/ListItem.js',
|
||||
|
||||
'Spaces/CockpitSpace.js',
|
||||
'Spaces/TopSpace.js',
|
||||
@@ -72,6 +73,7 @@ function newAppLoader() {
|
||||
'Spaces/ChartingSpace.js',
|
||||
'Spaces/FloatingSpace.js',
|
||||
'Spaces/DesignSpace.js',
|
||||
'Spaces/SideSpace.js',
|
||||
|
||||
'Files/SingleFile.js',
|
||||
'Files/FileCloud.js',
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 255 KiB After Width: | Height: | Size: 247 KiB |
+109
-13
@@ -55,19 +55,30 @@ exports.newWebServer = function newWebServer(EVENTS_SERVER) {
|
||||
if (CONSOLE_LOG === true && request.url.indexOf('NO-LOG') === -1) { console.log('[INFO] webServer -> onBrowserRequest -> request.url = ' + request.url) }
|
||||
|
||||
function getBody(callback) { // Gets the de body from a POST request to the web server
|
||||
let body = ''
|
||||
try {
|
||||
|
||||
request.on('data', function (data) {
|
||||
body += data
|
||||
// Too much POST data
|
||||
if (body.length > 1e6) {
|
||||
request.connection.destroy()
|
||||
}
|
||||
})
|
||||
let body = ''
|
||||
|
||||
request.on('end', function () {
|
||||
callback(body)
|
||||
})
|
||||
request.on('data', function (data) {
|
||||
body += data
|
||||
// Too much POST data
|
||||
//if (body.length > 1e6) {
|
||||
// request.connection.destroy()
|
||||
//}
|
||||
})
|
||||
|
||||
request.on('end', function () {
|
||||
callback(body)
|
||||
})
|
||||
|
||||
request.on('error', function (err) {
|
||||
if (CONSOLE_LOG === true) { console.log('[INFO] webServer -> onBrowserRequest -> getBody -> err = ' + err.stack) }
|
||||
respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), response)
|
||||
})
|
||||
} catch (err) {
|
||||
if (CONSOLE_LOG === true) { console.log('[INFO] webServer -> onBrowserRequest -> getBody -> err = ' + err.stack) }
|
||||
respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), response)
|
||||
}
|
||||
}
|
||||
|
||||
let requestParameters = request.url.split('/')
|
||||
@@ -170,8 +181,10 @@ exports.newWebServer = function newWebServer(EVENTS_SERVER) {
|
||||
}
|
||||
break
|
||||
}
|
||||
break
|
||||
|
||||
case 'Webhook': {
|
||||
case 'Webhook':
|
||||
{
|
||||
switch (requestParameters[2]) { // switch by command
|
||||
case 'Fetch-Messages': {
|
||||
let exchange = requestParameters[3]
|
||||
@@ -243,9 +256,10 @@ exports.newWebServer = function newWebServer(EVENTS_SERVER) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
break
|
||||
|
||||
case 'ResetLogsAndData':
|
||||
{
|
||||
try {
|
||||
@@ -378,6 +392,7 @@ exports.newWebServer = function newWebServer(EVENTS_SERVER) {
|
||||
respondWithFile(filePath, response)
|
||||
}
|
||||
break
|
||||
|
||||
case 'Panels':
|
||||
{
|
||||
respondWithFile(process.env.PATH_TO_CANVAS_APP + '/' + requestParameters[1] + '/' + requestParameters[2], response)
|
||||
@@ -420,6 +435,12 @@ exports.newWebServer = function newWebServer(EVENTS_SERVER) {
|
||||
}
|
||||
break
|
||||
|
||||
case 'SideSpace':
|
||||
{
|
||||
respondWithFile(process.env.PATH_TO_CANVAS_APP + '/' + requestParameters[1] + '/' + requestParameters[2], response)
|
||||
}
|
||||
break
|
||||
|
||||
case 'AppSchema.js':
|
||||
{
|
||||
let fs = require('fs')
|
||||
@@ -464,6 +485,81 @@ exports.newWebServer = function newWebServer(EVENTS_SERVER) {
|
||||
}
|
||||
break
|
||||
|
||||
case 'ListWorkspaces':
|
||||
{
|
||||
let dirPath = process.env.MY_WORKSPACES_PATH
|
||||
|
||||
try {
|
||||
let fs = require('fs')
|
||||
|
||||
fs.readdir(dirPath, onDirRead)
|
||||
|
||||
function onDirRead(err, fileList) {
|
||||
if (err) {
|
||||
if (CONSOLE_LOG === true) { console.log('[ERROR] Error reading a directory content. filePath = ' + dirPath) }
|
||||
respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), response)
|
||||
return
|
||||
} else {
|
||||
respondWithContent(JSON.stringify(fileList), response)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
if (CONSOLE_LOG === true) { console.log('[ERROR] Error reading a directory content. filePath = ' + dirPath) }
|
||||
respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), response)
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
break
|
||||
|
||||
case 'LoadWorkspace':
|
||||
{
|
||||
let fileName = unescape(requestParameters[2])
|
||||
let filePath = process.env.MY_WORKSPACES_PATH + '/' + fileName + '.json'
|
||||
respondWithFile(filePath, response)
|
||||
}
|
||||
break
|
||||
|
||||
case 'SaveWorkspace':
|
||||
{
|
||||
getBody(processRequest)
|
||||
|
||||
async function processRequest(body) {
|
||||
|
||||
let fileContent = body
|
||||
let fileName = unescape(requestParameters[2])
|
||||
let filePath = process.env.MY_WORKSPACES_PATH + '/' + fileName + '.json'
|
||||
|
||||
try {
|
||||
let fs = require('fs')
|
||||
let dir = process.env.MY_WORKSPACES_PATH;
|
||||
|
||||
/* Create Dir if it does not exist */
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir);
|
||||
}
|
||||
|
||||
fs.writeFile(filePath, fileContent, onFileWritten)
|
||||
|
||||
function onFileWritten(err) {
|
||||
if (err) {
|
||||
if (CONSOLE_LOG === true) { console.log('[ERROR] Error writting the Workspace file. fileName = ' + fileName) }
|
||||
respondWithContent(JSON.stringify(exchanges), response)
|
||||
} else {
|
||||
respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), response)
|
||||
}
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
if (CONSOLE_LOG === true) { console.log('[ERROR] Error writting the Workspace file. fileName = ' + fileName) }
|
||||
respondWithContent(JSON.stringify(exchanges), response)
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
|
||||
case 'DataMines':
|
||||
{
|
||||
respondWithFile(process.env.DATA_MINES_PATH + '/' + requestParameters[2] + '.json', response)
|
||||
|
||||
+11
-2
@@ -144,12 +144,20 @@ function newAnimation () {
|
||||
browserCanvas.height = 1
|
||||
}
|
||||
|
||||
/* Media Recording */
|
||||
/* Video Recording */
|
||||
videoRecorder.physics()
|
||||
if (areWeRecording === true) {
|
||||
if (ARE_WE_RECORDING_A_VIDEO === true) {
|
||||
videoRecorder.recordCanvas()
|
||||
}
|
||||
|
||||
/* Panorama Recording */
|
||||
if (ARE_WE_RECORDING_A_MARKET_PANORAMA === true) {
|
||||
if (PANORAMA_WAS_PANNED === true) {
|
||||
addToMarketPanorama()
|
||||
PANORAMA_WAS_PANNED = false
|
||||
}
|
||||
}
|
||||
|
||||
/* We request the next frame to be drawn, and stablishing a loop */
|
||||
|
||||
/* Use this code for full animation speed. */
|
||||
@@ -168,6 +176,7 @@ function newAnimation () {
|
||||
}
|
||||
|
||||
function clearBrowserCanvas () {
|
||||
if (canWeDraw === false) { return }
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', 1)'
|
||||
browserCanvasContext.clearRect(0, 0, browserCanvas.width, browserCanvas.height)
|
||||
}
|
||||
|
||||
+78
-46
@@ -3,7 +3,6 @@ let browserCanvasContext // The context of the canvas object.
|
||||
|
||||
let stepsInitializationCounter = 0 // This counter the initialization steps required to be able to turn off the splash screen.
|
||||
let marketInitializationCounter = 0 // This counter the initialization of markets required to be able to turn off the splash screen.
|
||||
let splashScreenNeeded = true
|
||||
|
||||
function newCanvas () {
|
||||
const MODULE_NAME = 'Canvas'
|
||||
@@ -32,12 +31,13 @@ function newCanvas () {
|
||||
let thisObject = {
|
||||
eventHandler: undefined,
|
||||
topSpace: undefined,
|
||||
sideSpace: undefined,
|
||||
chartingSpace: undefined,
|
||||
floatingSpace: undefined,
|
||||
panelsSpace: undefined,
|
||||
cockpitSpace: undefined,
|
||||
bottomSpace: undefined,
|
||||
designSpace: undefined,
|
||||
splashScreen: undefined,
|
||||
animation: undefined,
|
||||
mouse: undefined,
|
||||
shorcutNumbers: new Map(),
|
||||
@@ -47,7 +47,6 @@ function newCanvas () {
|
||||
|
||||
thisObject.eventHandler = newEventHandler()
|
||||
|
||||
let splashScreen
|
||||
let lastContainerMouseOver
|
||||
let lastShortcutKeyRejection
|
||||
|
||||
@@ -63,6 +62,7 @@ function newCanvas () {
|
||||
|
||||
function finalize () {
|
||||
try {
|
||||
thisObject.sideSpace.finalize()
|
||||
thisObject.chartingSpace.finalize()
|
||||
thisObject.floatingSpace.finalize()
|
||||
thisObject.shorcutNumbers = undefined
|
||||
@@ -86,7 +86,7 @@ function newCanvas () {
|
||||
browserCanvas.removeEventListener('keydown', onKeyDown, false)
|
||||
browserCanvas.removeEventListener('keyup', onKeyUp, false)
|
||||
|
||||
splashScreen = undefined
|
||||
thisObject.splashScreen = undefined
|
||||
lastContainerMouseOver = undefined
|
||||
|
||||
hisObject.mouse = undefined
|
||||
@@ -109,22 +109,22 @@ function newCanvas () {
|
||||
thisObject.topSpace = newTopSpace()
|
||||
thisObject.topSpace.initialize()
|
||||
|
||||
thisObject.designSpace = newDesignSpace()
|
||||
thisObject.designSpace.initialize()
|
||||
|
||||
thisObject.cockpitSpace = newCockpitSpace()
|
||||
thisObject.cockpitSpace.initialize()
|
||||
|
||||
thisObject.designSpace = newDesignSpace()
|
||||
thisObject.designSpace.initialize()
|
||||
|
||||
thisObject.panelsSpace = newPanelsSpace()
|
||||
thisObject.panelsSpace.initialize()
|
||||
|
||||
thisObject.chartingSpace = newChartingSpace()
|
||||
thisObject.chartingSpace.initialize()
|
||||
|
||||
thisObject.bottomSpace = thisObject.cockpitSpace
|
||||
thisObject.sideSpace = newSideSpace()
|
||||
thisObject.sideSpace.initialize()
|
||||
|
||||
splashScreen = newSplashScreen()
|
||||
splashScreen.initialize()
|
||||
thisObject.splashScreen = newSplashScreen()
|
||||
|
||||
let animation = newAnimation()
|
||||
animation.initialize()
|
||||
@@ -137,6 +137,7 @@ function newCanvas () {
|
||||
animation.addCallBackFunction('Charting Space Physics', thisObject.chartingSpace.physics)
|
||||
animation.addCallBackFunction('Design Space Physics', thisObject.designSpace.physics)
|
||||
animation.addCallBackFunction('Panels Space Physics', thisObject.panelsSpace.physics)
|
||||
animation.addCallBackFunction('Side Space Physics', thisObject.sideSpace.physics)
|
||||
|
||||
/* Spcaces Drawing */
|
||||
animation.addCallBackFunction('Floating Space Draw', thisObject.floatingSpace.draw)
|
||||
@@ -145,7 +146,8 @@ function newCanvas () {
|
||||
animation.addCallBackFunction('CockpitSpace Draw', thisObject.cockpitSpace.draw)
|
||||
animation.addCallBackFunction('Design Space Draw', thisObject.designSpace.draw)
|
||||
animation.addCallBackFunction('Top Space Draw', thisObject.topSpace.draw)
|
||||
animation.addCallBackFunction('Splash Screen Draw', splashScreen.draw)
|
||||
animation.addCallBackFunction('Side Space Draw', thisObject.sideSpace.draw)
|
||||
animation.addCallBackFunction('Splash Screen Draw', thisObject.splashScreen.draw)
|
||||
animation.start()
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] initialize -> err = ' + err.stack) }
|
||||
@@ -211,30 +213,35 @@ function newCanvas () {
|
||||
if ((event.ctrlKey === true || event.metaKey === true)) {
|
||||
let constructorParams
|
||||
switch (event.keyCode) {
|
||||
case 118: { // F7
|
||||
downloadPanorama('Superalgos.Market.Panorama')
|
||||
return
|
||||
break
|
||||
}
|
||||
case 119: { // F8
|
||||
downloadCanvas('Superalgos.image.capture')
|
||||
downloadCanvas('Superalgos.Image.Capture', browserCanvas)
|
||||
return
|
||||
break
|
||||
}
|
||||
case 120: { // F9
|
||||
constructorParams = { format: 'gif', workersPath: 'externalScripts/', framerate: 8, name: 'Superalgos.video.capture'}
|
||||
constructorParams = { format: 'gif', workersPath: 'externalScripts/', framerate: 8, name: 'Superalgos.Video.Capture'}
|
||||
break
|
||||
}
|
||||
case 121: { // F10
|
||||
constructorParams = { format: 'webm', framerate: 8, name: 'Superalgos.video.capture' }
|
||||
constructorParams = { format: 'webm', framerate: 8, name: 'Superalgos.Video.Capture' }
|
||||
break
|
||||
}
|
||||
default: return
|
||||
}
|
||||
|
||||
if (areWeRecording === false) {
|
||||
if (ARE_WE_RECORDING_A_VIDEO === false) {
|
||||
console.log('RECORDING', constructorParams.format)
|
||||
mediaRecorder = new CCapture(constructorParams)
|
||||
mediaRecorder.start()
|
||||
areWeRecording = true
|
||||
ARE_WE_RECORDING_A_VIDEO = true
|
||||
} else {
|
||||
console.log('SAVING', constructorParams.format)
|
||||
areWeRecording = false
|
||||
ARE_WE_RECORDING_A_VIDEO = false
|
||||
mediaRecorder.stop()
|
||||
mediaRecorder.save()
|
||||
}
|
||||
@@ -295,11 +302,7 @@ function newCanvas () {
|
||||
}
|
||||
|
||||
if (event.shiftKey === true && (event.ctrlKey === true || event.metaKey === true) && (event.key === 'S' || event.key === 's')) {
|
||||
let saved = canvas.designSpace.workspace.save()
|
||||
if (saved === true) {
|
||||
canvas.cockpitSpace.setStatus('Workspace Saved.', 50, canvas.cockpitSpace.statusTypes.ALL_GOOD)
|
||||
}
|
||||
|
||||
canvas.designSpace.workspace.save()
|
||||
event.preventDefault()
|
||||
return
|
||||
}
|
||||
@@ -578,8 +581,21 @@ function newCanvas () {
|
||||
|
||||
let container
|
||||
|
||||
/* We check if the mouse is over an element of the Design Space / */
|
||||
/* We check if the mouse is over an element of the Side Space / */
|
||||
container = thisObject.sideSpace.getContainer(point)
|
||||
|
||||
if (container !== undefined && container.isDraggeable === true) {
|
||||
containerBeingDragged = container
|
||||
containerDragStarted = true
|
||||
containerBeingDragged.eventHandler.raiseEvent('onDragStarted', point)
|
||||
return
|
||||
}
|
||||
|
||||
if (container !== undefined && container.isDraggeable === false) {
|
||||
return
|
||||
}
|
||||
|
||||
/* We check if the mouse is over an element of the Design Space / */
|
||||
container = thisObject.designSpace.getContainer(point)
|
||||
|
||||
if (container !== undefined && container.isDraggeable === true) {
|
||||
@@ -593,8 +609,7 @@ function newCanvas () {
|
||||
return
|
||||
}
|
||||
|
||||
/* We check if the mouse is over an element of the Top Space / */
|
||||
|
||||
/* We check if the mouse is over an element of the Top Space / */
|
||||
container = thisObject.topSpace.getContainer(point)
|
||||
|
||||
if (container !== undefined && container.isDraggeable === true) {
|
||||
@@ -604,8 +619,7 @@ function newCanvas () {
|
||||
return
|
||||
}
|
||||
|
||||
/* We check if the mouse is over an element of the CockpitSpace / */
|
||||
|
||||
/* We check if the mouse is over an element of the CockpitSpace / */
|
||||
container = thisObject.cockpitSpace.getContainer(point)
|
||||
|
||||
if (container !== undefined && container.isDraggeable === true) {
|
||||
@@ -620,8 +634,7 @@ function newCanvas () {
|
||||
return
|
||||
}
|
||||
|
||||
/* We check if the mouse is over a panel/ */
|
||||
|
||||
/* We check if the mouse is over a panel/ */
|
||||
container = thisObject.panelsSpace.getContainer(point, GET_CONTAINER_PURPOSE.DRAGGING)
|
||||
|
||||
if (container !== undefined && event.shiftKey === false) {
|
||||
@@ -640,8 +653,7 @@ function newCanvas () {
|
||||
return
|
||||
}
|
||||
|
||||
/* we check if it is over any of the existing containers at the Charting Space. */
|
||||
|
||||
/* we check if it is over any of the existing containers at the Charting Space. */
|
||||
container = thisObject.chartingSpace.getContainer(point, GET_CONTAINER_PURPOSE.DRAGGING)
|
||||
|
||||
if (container !== undefined) {
|
||||
@@ -698,8 +710,15 @@ function newCanvas () {
|
||||
|
||||
let container
|
||||
|
||||
/* We check if the mouse is over an element of the Design Space / */
|
||||
/* We check if the mouse is over an element of the Side Space / */
|
||||
container = thisObject.sideSpace.getContainer(point, GET_CONTAINER_PURPOSE.MOUSE_CLICK)
|
||||
|
||||
if (container !== undefined && container.isClickeable === true) {
|
||||
container.eventHandler.raiseEvent('onMouseClick', point)
|
||||
return
|
||||
}
|
||||
|
||||
/* We check if the mouse is over an element of the Design Space / */
|
||||
container = thisObject.designSpace.getContainer(point)
|
||||
|
||||
if (container !== undefined && container.isClickeable === true) {
|
||||
@@ -707,8 +726,7 @@ function newCanvas () {
|
||||
return
|
||||
}
|
||||
|
||||
/* We check if the mouse is over an element of the Top Space / */
|
||||
|
||||
/* We check if the mouse is over an element of the Top Space / */
|
||||
container = thisObject.topSpace.getContainer(point)
|
||||
|
||||
if (container !== undefined && container.isClickeable === true) {
|
||||
@@ -716,8 +734,7 @@ function newCanvas () {
|
||||
return
|
||||
}
|
||||
|
||||
/* We check if the mouse is over an element of the CockpitSpace / */
|
||||
|
||||
/* We check if the mouse is over an element of the CockpitSpace / */
|
||||
container = thisObject.cockpitSpace.getContainer(point)
|
||||
|
||||
if (container !== undefined && container.isClickeable === true) {
|
||||
@@ -725,8 +742,7 @@ function newCanvas () {
|
||||
return
|
||||
}
|
||||
|
||||
/* We check if the mouse is over a panel/ */
|
||||
|
||||
/* We check if the mouse is over a panel/ */
|
||||
container = thisObject.panelsSpace.getContainer(point, GET_CONTAINER_PURPOSE.MOUSE_CLICK)
|
||||
|
||||
if (container !== undefined && container.isClickeable === true) {
|
||||
@@ -734,8 +750,7 @@ function newCanvas () {
|
||||
return
|
||||
}
|
||||
|
||||
/* If it is not, then we check if it is over any of the existing containers at the Charting Space. */
|
||||
|
||||
/* If it is not, then we check if it is over any of the existing containers at the Charting Space. */
|
||||
container = thisObject.chartingSpace.getContainer(point, GET_CONTAINER_PURPOSE.MOUSE_CLICK)
|
||||
|
||||
if (container !== undefined && container.isClickeable === true) {
|
||||
@@ -837,6 +852,16 @@ function newCanvas () {
|
||||
|
||||
let container
|
||||
|
||||
/* We check if the mouse is over an element of the Designe Space / */
|
||||
if (thisObject.sideSpace !== undefined) {
|
||||
container = thisObject.sideSpace.getContainer(point, GET_CONTAINER_PURPOSE.MOUSE_OVER)
|
||||
|
||||
if (container !== undefined && container.detectMouseOver === true) {
|
||||
containerFound()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
/* We check if the mouse is over an element of the Designe Space / */
|
||||
if (thisObject.designSpace !== undefined) {
|
||||
container = thisObject.designSpace.getContainer(point)
|
||||
@@ -934,6 +959,16 @@ function newCanvas () {
|
||||
|
||||
event.mousePosition = point
|
||||
let container
|
||||
|
||||
/* Side Space */
|
||||
container = canvas.sideSpace.getContainer({ x: point.x, y: point.y })
|
||||
|
||||
if (container !== undefined && container.isWheelable === true) {
|
||||
container.eventHandler.raiseEvent('onMouseWheel', event)
|
||||
return false // This instructs the browser not to take the event and scroll the page.
|
||||
}
|
||||
|
||||
/* Panel Space */
|
||||
container = canvas.panelsSpace.getContainer({ x: point.x, y: point.y })
|
||||
|
||||
if (container !== undefined && container.isWheelable === true) {
|
||||
@@ -941,8 +976,7 @@ function newCanvas () {
|
||||
return false // This instructs the browser not to take the event and scroll the page.
|
||||
}
|
||||
|
||||
/* We try the CockpitSpace. */
|
||||
|
||||
/* We try the CockpitSpace. */
|
||||
container = canvas.cockpitSpace.getContainer({ x: point.x, y: point.y })
|
||||
|
||||
if (container !== undefined && container.isWheelable === true) {
|
||||
@@ -950,8 +984,7 @@ function newCanvas () {
|
||||
return false // This instructs the browser not to take the event and scroll the page.
|
||||
}
|
||||
|
||||
/* Charting Space. */
|
||||
|
||||
/* Charting Space. */
|
||||
container = canvas.chartingSpace.getContainer({ x: point.x, y: point.y }, GET_CONTAINER_PURPOSE.MOUSE_WHEEL)
|
||||
if (container !== undefined && container.isWheelable === true) {
|
||||
container.eventHandler.raiseEvent('onMouseWheel', event)
|
||||
@@ -963,8 +996,7 @@ function newCanvas () {
|
||||
return false
|
||||
}
|
||||
|
||||
/* We try second with floating objects. */
|
||||
|
||||
/* We try second with floating objects. */
|
||||
container = canvas.floatingSpace.getContainer({ x: point.x, y: point.y })
|
||||
|
||||
if (container !== undefined && container.isWheelable === true) {
|
||||
|
||||
@@ -195,9 +195,18 @@ function newEdgeEditor () {
|
||||
}
|
||||
|
||||
if (event.shiftKey === false && event.ctrlKey === false && event.code === 'ArrowRight') {
|
||||
onDragStarted(event)
|
||||
thisObject.container.frame.position.x = thisObject.container.frame.position.x - STEP
|
||||
whatHappened = 'left or right arrow key pressed'
|
||||
if (ARE_WE_RECORDING_A_MARKET_PANORAMA === true) {
|
||||
if (PANORAMA_WAS_PANNED === false) {
|
||||
PANORAMA_WAS_PANNED = true
|
||||
onDragStarted(event)
|
||||
thisObject.container.frame.position.x = thisObject.container.frame.position.x - STEP * 2
|
||||
whatHappened = 'left or right arrow key pressed'
|
||||
}
|
||||
} else {
|
||||
onDragStarted(event)
|
||||
thisObject.container.frame.position.x = thisObject.container.frame.position.x - STEP
|
||||
whatHappened = 'left or right arrow key pressed'
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -181,18 +181,6 @@ function newSpeedometer () {
|
||||
|
||||
/* We put the thisObject.params.VALUE in the middle */
|
||||
|
||||
fontSize = 22
|
||||
if (thisObject.params.VALUE > 999) {
|
||||
fontSize = 18
|
||||
}
|
||||
if (thisObject.params.VALUE > 9999) {
|
||||
fontSize = 14
|
||||
}
|
||||
if (thisObject.params.VALUE > 99999) {
|
||||
fontSize = 10
|
||||
}
|
||||
browserCanvasContext.font = 'bold ' + fontSize + 'px ' + UI_FONT.PRIMARY
|
||||
|
||||
label = thisObject.params.VALUE
|
||||
|
||||
if (isNaN(label) === false) {
|
||||
@@ -202,6 +190,22 @@ function newSpeedometer () {
|
||||
if (label === 0) { label = label.toFixed(2) }
|
||||
}
|
||||
|
||||
fontSize = 22
|
||||
if (label.length > 8) {
|
||||
fontSize = 18
|
||||
}
|
||||
if (label.length > 10) {
|
||||
fontSize = 14
|
||||
}
|
||||
if (label.length > 12) {
|
||||
fontSize = 10
|
||||
}
|
||||
if (label.length > 14) {
|
||||
fontSize = 8
|
||||
}
|
||||
|
||||
browserCanvasContext.font = 'bold ' + fontSize + 'px ' + UI_FONT.PRIMARY
|
||||
|
||||
// label = label.substring(0, 6)
|
||||
|
||||
xOffset = label.length / 2 * fontSize * FONT_ASPECT_RATIO + 7
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
function newUiObjectsFromNodes () {
|
||||
thisObject = {
|
||||
runTasks: runTasks,
|
||||
runSessions: runSessions,
|
||||
recreateWorkspace: recreateWorkspace,
|
||||
tryToConnectChildrenWithReferenceParents: tryToConnectChildrenWithReferenceParents,
|
||||
createUiObjectFromNode: createUiObjectFromNode,
|
||||
@@ -14,7 +16,7 @@ function newUiObjectsFromNodes () {
|
||||
|
||||
return thisObject
|
||||
|
||||
function recreateWorkspace (node, replacingCurrentWorkspace) {
|
||||
function recreateWorkspace (node, callBackFunction) {
|
||||
mapOfNodes = new Map()
|
||||
tasksToRun = []
|
||||
sessionsToRun = []
|
||||
@@ -22,7 +24,7 @@ function newUiObjectsFromNodes () {
|
||||
addIncludedNodes()
|
||||
|
||||
function addIncludedNodes () {
|
||||
blobService = newFileStorage()
|
||||
let blobService = newFileStorage()
|
||||
|
||||
// if (node.code === undefined) {
|
||||
node.code = '{ \n"includeDataMines": ["Masters", "Sparta", "TradingEngines"],\n"includeTradingSystems": ["Sparta-WHB-BTC-USDT", "Example-ETH-USDT", "Sparta-BRR-BTC-USDT"],\n"includeSuperScripts": ["Masters"]\n }'
|
||||
@@ -135,15 +137,8 @@ function newUiObjectsFromNodes () {
|
||||
|
||||
tryToConnectChildrenWithReferenceParents()
|
||||
|
||||
if (replacingCurrentWorkspace === true) {
|
||||
// We need to wait all tasks that were potentially running to stop
|
||||
setTimeout(runTasks, 70000)
|
||||
// We give a few seconds for the tasks to start
|
||||
setTimeout(runSessions, 80000)
|
||||
} else {
|
||||
runTasks()
|
||||
// We give a few seconds for the tasks to start
|
||||
setTimeout(runSessions, 10000)
|
||||
if (callBackFunction !== undefined) {
|
||||
callBackFunction() // The recreation of the workspace is complete
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ function newWorkspace () {
|
||||
enabled: false,
|
||||
nodeChildren: undefined,
|
||||
eventsServerClients: new Map(),
|
||||
replaceWorkspaceByLoadingOne: replaceWorkspaceByLoadingOne,
|
||||
save: saveWorkspace,
|
||||
getHierarchyHeads: getHierarchyHeads,
|
||||
getNodeThatIsOnFocus: getNodeThatIsOnFocus,
|
||||
@@ -68,7 +69,7 @@ function newWorkspace () {
|
||||
let workingAtTask = 0
|
||||
let circularProgressBar = newBusyProgressBar()
|
||||
circularProgressBar.fitFunction = canvas.floatingSpace.fitIntoVisibleArea
|
||||
let droppedNode
|
||||
let loadedWorkspaceNode
|
||||
let sessionTimestamp = (new Date()).valueOf()
|
||||
window.localStorage.setItem('Session Timestamp', sessionTimestamp)
|
||||
|
||||
@@ -85,24 +86,56 @@ function newWorkspace () {
|
||||
|
||||
function initialize () {
|
||||
try {
|
||||
let reset = window.localStorage.getItem('Reset')
|
||||
let savedWorkspace = window.localStorage.getItem(CANVAS_APP_NAME + '.' + 'Workspace')
|
||||
let lastUsedWorkspace = window.localStorage.getItem('Last Used Workspace')
|
||||
|
||||
if (savedWorkspace === null || reset !== null) {
|
||||
thisObject.workspaceNode = getWorkspace()
|
||||
if (lastUsedWorkspace !== 'undefined' && lastUsedWorkspace !== null && lastUsedWorkspace !== undefined) {
|
||||
let blobService = newFileStorage()
|
||||
blobService.getFileFromHost('LoadWorkspace' + '/' + lastUsedWorkspace, onFileReceived, true)
|
||||
function onFileReceived (err, text, response) {
|
||||
if (err && err.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) {
|
||||
canvas.cockpitSpace.setStatus('Could not load the last Workspace used, called "' + lastUsedWorkspace + '". Will switch to the default Workspace instead.', 500, canvas.cockpitSpace.statusTypes.WARNING)
|
||||
thisObject.workspaceNode = getWorkspace() // This is the default workspace that comes with the system.
|
||||
recreateWorkspace()
|
||||
return
|
||||
}
|
||||
thisObject.workspaceNode = JSON.parse(text)
|
||||
recreateWorkspace()
|
||||
}
|
||||
} else {
|
||||
thisObject.workspaceNode = JSON.parse(savedWorkspace)
|
||||
thisObject.workspaceNode = getWorkspace() // This is the default workspace that comes with the system.
|
||||
recreateWorkspace()
|
||||
}
|
||||
functionLibraryUiObjectsFromNodes.recreateWorkspace(thisObject.workspaceNode)
|
||||
setupEventsServerClients()
|
||||
thisObject.enabled = true
|
||||
|
||||
setInterval(saveWorkspace, 60000)
|
||||
function recreateWorkspace () {
|
||||
functionLibraryUiObjectsFromNodes.recreateWorkspace(thisObject.workspaceNode, finishInitialization)
|
||||
}
|
||||
|
||||
function finishInitialization () {
|
||||
setupEventsServerClients()
|
||||
runTasksAndSessions(false)
|
||||
thisObject.enabled = true
|
||||
canvas.cockpitSpace.initializePosition()
|
||||
canvas.splashScreen.initialize()
|
||||
setInterval(saveWorkspace, 60000)
|
||||
}
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] initialize -> err = ' + err.stack) }
|
||||
}
|
||||
}
|
||||
|
||||
function runTasksAndSessions (replacingCurrentWorkspace) {
|
||||
if (replacingCurrentWorkspace === true) {
|
||||
// We need to wait all tasks that were potentially running to stop
|
||||
setTimeout(functionLibraryUiObjectsFromNodes.runTasks, 70000)
|
||||
// We give a few seconds for the tasks to start
|
||||
setTimeout(functionLibraryUiObjectsFromNodes.runSessions, 80000)
|
||||
} else {
|
||||
functionLibraryUiObjectsFromNodes.runTasks()
|
||||
// We give a few seconds for the tasks to start
|
||||
setTimeout(functionLibraryUiObjectsFromNodes.runSessions, 10000)
|
||||
}
|
||||
}
|
||||
|
||||
function setupEventsServerClients () {
|
||||
for (let i = 0; i < thisObject.workspaceNode.rootNodes.length; i++) {
|
||||
let rootNode = thisObject.workspaceNode.rootNodes[i]
|
||||
@@ -170,6 +203,23 @@ function newWorkspace () {
|
||||
let textToSave = stringifyWorkspace()
|
||||
window.localStorage.setItem(CANVAS_APP_NAME + '.' + 'Workspace', textToSave)
|
||||
window.localStorage.setItem('Session Timestamp', sessionTimestamp)
|
||||
|
||||
if (workspace.name !== undefined) {
|
||||
let url = 'SaveWorkspace/' + workspace.name
|
||||
callServer(textToSave, url, onResponse)
|
||||
}
|
||||
|
||||
function onResponse (err) {
|
||||
if (err.result === GLOBAL.DEFAULT_OK_RESPONSE.result) {
|
||||
window.localStorage.setItem('Last Used Workspace', workspace.name)
|
||||
window.localStorage.setItem('Session Timestamp', sessionTimestamp)
|
||||
if (ARE_WE_RECORDING_A_MARKET_PANORAMA === false) {
|
||||
canvas.cockpitSpace.setStatus(workspace.name + ' Saved.', 50, canvas.cockpitSpace.statusTypes.ALL_GOOD)
|
||||
}
|
||||
} else {
|
||||
canvas.cockpitSpace.setStatus('Could not save the Workspace at the Backend. Please check the Backend Console for more information.', 150, canvas.cockpitSpace.statusTypes.WARNING)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -203,13 +253,14 @@ function newWorkspace () {
|
||||
workingAtTask++
|
||||
break
|
||||
case 3:
|
||||
thisObject.workspaceNode = droppedNode
|
||||
droppedNode = undefined
|
||||
thisObject.workspaceNode = loadedWorkspaceNode
|
||||
loadedWorkspaceNode = undefined
|
||||
workingAtTask++
|
||||
break
|
||||
case 4:
|
||||
functionLibraryUiObjectsFromNodes.recreateWorkspace(thisObject.workspaceNode, true)
|
||||
functionLibraryUiObjectsFromNodes.recreateWorkspace(thisObject.workspaceNode)
|
||||
setupEventsServerClients()
|
||||
runTasksAndSessions(true)
|
||||
workingAtTask++
|
||||
break
|
||||
case 5:
|
||||
@@ -304,6 +355,30 @@ function newWorkspace () {
|
||||
return nodes
|
||||
}
|
||||
|
||||
function replaceWorkspaceByLoadingOne (name) {
|
||||
let blobService = newFileStorage()
|
||||
blobService.getFileFromHost('LoadWorkspace' + '/' + name, onFileReceived, true)
|
||||
function onFileReceived (err, text, response) {
|
||||
if (err && err.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) {
|
||||
canvas.cockpitSpace.setStatus('Could not load the Workspace called "' + name + '". ', 500, canvas.cockpitSpace.statusTypes.WARNING)
|
||||
return
|
||||
}
|
||||
|
||||
loadedWorkspaceNode = JSON.parse(text)
|
||||
saveWorkspace()
|
||||
canvas.cockpitSpace.toTop()
|
||||
|
||||
let position = {
|
||||
x: browserCanvas.width / 2,
|
||||
y: browserCanvas.height / 2
|
||||
}
|
||||
|
||||
circularProgressBar.initialize(position)
|
||||
circularProgressBar.visible = true
|
||||
workingAtTask = 1
|
||||
}
|
||||
}
|
||||
|
||||
function spawn (nodeText, mousePointer) {
|
||||
try {
|
||||
let point = {
|
||||
@@ -314,9 +389,10 @@ function newWorkspace () {
|
||||
spawnPosition.x = point.x
|
||||
spawnPosition.y = point.y
|
||||
|
||||
droppedNode = JSON.parse(nodeText)
|
||||
let droppedNode = JSON.parse(nodeText)
|
||||
|
||||
if (droppedNode.type === 'Workspace') {
|
||||
loadedWorkspaceNode = droppedNode
|
||||
circularProgressBar.initialize(mousePointer)
|
||||
circularProgressBar.visible = true
|
||||
workingAtTask = 1
|
||||
@@ -508,6 +584,16 @@ function newWorkspace () {
|
||||
referenceDetachNode(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Push Code to Javascript Code':
|
||||
{
|
||||
payload.node.javascriptCode.code = payload.node.code
|
||||
}
|
||||
break
|
||||
case 'Fetch Code to Javascript Code':
|
||||
{
|
||||
payload.node.code = payload.node.javascriptCode.code
|
||||
}
|
||||
break
|
||||
case 'Open Documentation':
|
||||
{
|
||||
let definition = APP_SCHEMA_MAP.get(payload.node.type)
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -25,8 +25,8 @@ function newPicker () {
|
||||
thisObject.container.frame.radius = 0
|
||||
thisObject.container.frame.position.x = 0
|
||||
thisObject.container.frame.position.y = 0
|
||||
thisObject.container.frame.width = 200
|
||||
thisObject.container.frame.height = 120
|
||||
thisObject.container.frame.width = 150
|
||||
thisObject.container.frame.height = 60
|
||||
|
||||
let isMouseOver
|
||||
let optionsList
|
||||
@@ -175,7 +175,7 @@ function newPicker () {
|
||||
}
|
||||
|
||||
function drawForeground () {
|
||||
const FONT_SIZE = 20
|
||||
const FONT_SIZE = 15
|
||||
const VISIBLE_LABELS = 5
|
||||
let fontSize
|
||||
let fontColor
|
||||
@@ -190,11 +190,11 @@ function newPicker () {
|
||||
fontColor = UI_COLOR.LIGHT_GREY
|
||||
switch (i) {
|
||||
case 0:
|
||||
fontSize = FONT_SIZE - 10
|
||||
fontSize = FONT_SIZE - 5
|
||||
opacity = 0.4
|
||||
break
|
||||
case 1:
|
||||
fontSize = FONT_SIZE - 5
|
||||
fontSize = FONT_SIZE - 3
|
||||
opacity = 0.5
|
||||
break
|
||||
case 2:
|
||||
@@ -203,11 +203,11 @@ function newPicker () {
|
||||
opacity = 1
|
||||
break
|
||||
case 3:
|
||||
fontSize = FONT_SIZE - 5
|
||||
fontSize = FONT_SIZE - 3
|
||||
opacity = 0.5
|
||||
break
|
||||
case 4:
|
||||
fontSize = FONT_SIZE - 10
|
||||
fontSize = FONT_SIZE - 5
|
||||
opacity = 0.4
|
||||
break
|
||||
}
|
||||
|
||||
@@ -1205,7 +1205,26 @@ function newUiObject () {
|
||||
}
|
||||
}
|
||||
|
||||
function isEditorVisible () {
|
||||
if (thisObject.codeEditor !== undefined) {
|
||||
if (thisObject.codeEditor.visible === true) { return true }
|
||||
}
|
||||
|
||||
if (thisObject.configEditor !== undefined) {
|
||||
if (thisObject.configEditor.visible === true) { return true }
|
||||
}
|
||||
|
||||
if (thisObject.conditionEditor !== undefined) {
|
||||
if (thisObject.conditionEditor.visible === true) { return true }
|
||||
}
|
||||
|
||||
if (thisObject.formulaEditor !== undefined) {
|
||||
if (thisObject.formulaEditor.visible === true) { return true }
|
||||
}
|
||||
}
|
||||
|
||||
function drawText () {
|
||||
if (isEditorVisible() === true) { return }
|
||||
/* Text Follows */
|
||||
let position = {
|
||||
x: 0,
|
||||
@@ -1332,7 +1351,7 @@ function newUiObject () {
|
||||
label = currentValue
|
||||
if (!isNaN(label)) {
|
||||
if (currentValue.toFixed !== undefined) {
|
||||
label = currentValue.toFixed(2)
|
||||
label = dynamicDecimals(currentValue, 2)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -190,8 +190,7 @@ const MAX_PLOTABLE_DATE = maxDate;
|
||||
|
||||
const TOP_SPACE_HEIGHT = 40
|
||||
const COCKPIT_SPACE_HEIGHT = 30;
|
||||
const BREAKPOINT_HEIGHT = 15;
|
||||
const SIDE_PANEL_WIDTH = 450
|
||||
const SIDE_PANEL_WIDTH = 350
|
||||
let COCKPIT_SPACE_POSITION = browserCanvas.height - COCKPIT_SPACE_HEIGHT
|
||||
|
||||
const LAYER_STATUS = {
|
||||
@@ -222,7 +221,13 @@ const TIME_MACHINE_WIDTH = 8;
|
||||
const TIME_MACHINE_HEIGHT = 8;
|
||||
|
||||
let mediaRecorder // to downloadText canvas animation as a mediaRecorder
|
||||
let areWeRecording = false
|
||||
let marketPanoramaCanvas
|
||||
let ARE_WE_RECORDING_A_VIDEO = false
|
||||
let ARE_WE_RECORDING_A_MARKET_PANORAMA = false
|
||||
let PANORAMA_WAS_PANNED = false
|
||||
let CURRENT_PANORAMA_POSITION = 0
|
||||
|
||||
let canWeDraw = false // This global variable regulates when spaces can or can not draw their contents.
|
||||
|
||||
function toRadians(angle) {
|
||||
return angle * (Math.PI / 180);
|
||||
|
||||
@@ -170,7 +170,7 @@ function newLayer () {
|
||||
'Plotter Module->Plotter->' +
|
||||
'Shapes->' +
|
||||
'Chart Points->Point->Point Formula->' +
|
||||
'Polygon->Polygon Body->Style->Style Condition->Style->' +
|
||||
'Polygon->Polygon Condition->Polygon Body->Style->Style Condition->Style->' +
|
||||
'Polygon Border->Style->Style Condition->Style->' +
|
||||
'Polygon Vertex->Point->' +
|
||||
'Plotter Panel->Javascript Code->Panel Data->Data Formula->'
|
||||
|
||||
@@ -154,7 +154,7 @@ function newPlotterPanel () {
|
||||
if (panelData.code.valueDecimals !== undefined) {
|
||||
if (value !== undefined) {
|
||||
if (isNaN(value) === false) {
|
||||
value = value.toFixed(panelData.code.valueDecimals)
|
||||
value = dynamicDecimals(value, panelData.code.valueDecimals)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+16
-4
@@ -570,23 +570,23 @@ function newPlotter () {
|
||||
let x = 0
|
||||
let y = 0
|
||||
eval(point.pointFormula.code)
|
||||
let dataPoint = {
|
||||
let rawPoint = {
|
||||
x: x,
|
||||
y: y
|
||||
}
|
||||
/* Contributing to Auto-Scale */
|
||||
coordinateSystem.reportYValue(dataPoint.y)
|
||||
|
||||
/*
|
||||
The information we store in files is independent from the charing system and its coordinate systems.
|
||||
That means that the first thing we allways need to do is to trasform these points to the coordinate system of the timeline.
|
||||
*/
|
||||
dataPoint = coordinateSystem.transformThisPoint(dataPoint)
|
||||
let dataPoint
|
||||
dataPoint = coordinateSystem.transformThisPoint(rawPoint)
|
||||
dataPoint = transformThisPoint(dataPoint, thisObject.container)
|
||||
dataPoint = canvas.chartingSpace.viewport.fitIntoVisibleArea(dataPoint)
|
||||
dataPoint = thisObject.fitFunction(dataPoint)
|
||||
|
||||
/* Store the data point at the local map */
|
||||
dataPoint.rawPoint = rawPoint
|
||||
dataPoints.set(point.id, dataPoint)
|
||||
}
|
||||
}
|
||||
@@ -598,6 +598,12 @@ function newPlotter () {
|
||||
|
||||
for (let j = 0; j < productDefinition.referenceParent.shapes.polygons.length; j++) {
|
||||
let polygon = productDefinition.referenceParent.shapes.polygons[j]
|
||||
/* We will check if we need to plot this Polygon or not. */
|
||||
if (polygon.polygonCondition !== undefined) {
|
||||
let mustPlot = eval(polygon.polygonCondition.code)
|
||||
if (mustPlot !== true) { continue }
|
||||
}
|
||||
|
||||
let calculatedStyle
|
||||
|
||||
/* Finding out the fill style */
|
||||
@@ -724,6 +730,12 @@ function newPlotter () {
|
||||
console.log('[WARN] You have a Polygon Vertex not referencing any Point.')
|
||||
continue
|
||||
}
|
||||
|
||||
/* Contributing to Auto-Scale */
|
||||
if (dataPointObject.rawPoint.y > 1 && dataPointObject.rawPoint.y !== undefined && isNaN(dataPointObject.rawPoint.y) === false) {
|
||||
coordinateSystem.reportYValue(dataPointObject.rawPoint.y)
|
||||
}
|
||||
|
||||
let dataPoint = {
|
||||
x: dataPointObject.x,
|
||||
y: dataPointObject.y
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
function newListItem () {
|
||||
const MODULE_NAME = 'List Item'
|
||||
const ERROR_LOG = true
|
||||
const logger = newWebDebugLog()
|
||||
logger.fileName = MODULE_NAME
|
||||
|
||||
let thisObject = {
|
||||
container: undefined,
|
||||
fitFunction: undefined,
|
||||
physics: physics,
|
||||
draw: draw,
|
||||
getContainer: getContainer,
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
}
|
||||
|
||||
thisObject.container = newContainer()
|
||||
thisObject.container.initialize()
|
||||
thisObject.container.isDraggeable = false
|
||||
thisObject.container.isWheelable = false
|
||||
thisObject.container.detectMouseOver = true
|
||||
thisObject.container.isClickeable = true
|
||||
thisObject.container.frame.width = SIDE_PANEL_WIDTH * 0.75
|
||||
thisObject.container.frame.height = SIDE_PANEL_WIDTH * 0.75
|
||||
|
||||
let name
|
||||
let type
|
||||
|
||||
let onMouseOverEventSubscriptionId
|
||||
let onMouseNotOverEventSubscriptionId
|
||||
let onMouseClickEventSubscriptionId
|
||||
|
||||
let isMouseOver = false
|
||||
return thisObject
|
||||
|
||||
function finalize () {
|
||||
thisObject.container.eventHandler.stopListening(onMouseOverEventSubscriptionId)
|
||||
thisObject.container.eventHandler.stopListening(onMouseNotOverEventSubscriptionId)
|
||||
thisObject.container.eventHandler.stopListening(onMouseClickEventSubscriptionId)
|
||||
|
||||
thisObject.container.finalize()
|
||||
thisObject.container = undefined
|
||||
thisObject.fitFunction = undefined
|
||||
}
|
||||
|
||||
function initialize (pName, pType) {
|
||||
name = pName
|
||||
type = pType
|
||||
|
||||
onMouseOverEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseOver', onMouseOver)
|
||||
onMouseNotOverEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseNotOver', onMouseNotOver)
|
||||
onMouseClickEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseClick', onMouseClick)
|
||||
}
|
||||
|
||||
function getContainer (point) {
|
||||
if (thisObject.container.frame.isThisPointHere(point, true) === true) {
|
||||
return thisObject.container
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseOver (event) {
|
||||
isMouseOver = true
|
||||
}
|
||||
|
||||
function onMouseNotOver () {
|
||||
isMouseOver = false
|
||||
}
|
||||
|
||||
function onMouseClick (event) {
|
||||
canvas.designSpace.workspace.replaceWorkspaceByLoadingOne(name)
|
||||
}
|
||||
|
||||
function physics () {
|
||||
|
||||
}
|
||||
|
||||
function draw () {
|
||||
let icon = canvas.designSpace.iconByUiObjectType.get(type)
|
||||
let backgroundColor = UI_COLOR.BLACK
|
||||
let labelColor
|
||||
|
||||
const RED_LINE_HIGHT = 4
|
||||
const OPACITY = 1
|
||||
|
||||
let params = {
|
||||
cornerRadius: 0,
|
||||
lineWidth: 1,
|
||||
container: thisObject.container,
|
||||
borderColor: UI_COLOR.RUSTED_RED,
|
||||
castShadow: false,
|
||||
backgroundColor: backgroundColor,
|
||||
opacity: OPACITY
|
||||
}
|
||||
|
||||
if (isMouseOver === false) {
|
||||
labelColor = UI_COLOR.WHITE
|
||||
} else {
|
||||
labelColor = UI_COLOR.TITANIUM_YELLOW
|
||||
}
|
||||
|
||||
roundedCornersBackground(params)
|
||||
|
||||
drawLabel(name, 1 / 2, 3.0 / 10, -5, 0, 15, thisObject.container, labelColor)
|
||||
drawLabel(type, 1 / 2, 7.2 / 10, -5, 0, 15, thisObject.container, labelColor)
|
||||
drawIcon(icon, 1 / 2, 1 / 2, 0, 0, 80, thisObject.container)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
function newListView () {
|
||||
const MODULE_NAME = 'List View'
|
||||
const ERROR_LOG = true
|
||||
const logger = newWebDebugLog()
|
||||
logger.fileName = MODULE_NAME
|
||||
|
||||
let thisObject = {
|
||||
fitFunction: undefined,
|
||||
container: undefined,
|
||||
listItems: [],
|
||||
payload: undefined,
|
||||
isVisible: false,
|
||||
resize: resize,
|
||||
turnOn: turnOn,
|
||||
turnOff: turnOff,
|
||||
physics: physics,
|
||||
draw: draw,
|
||||
getContainer: getContainer,
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
}
|
||||
|
||||
thisObject.container = newContainer()
|
||||
thisObject.container.initialize()
|
||||
thisObject.container.isDraggeable = false
|
||||
thisObject.container.isWheelable = true
|
||||
thisObject.container.detectMouseOver = true
|
||||
|
||||
let isInitialized = false
|
||||
|
||||
let listItemsMap = new Map()
|
||||
let visibleListItems = []
|
||||
let firstVisibleListItem
|
||||
|
||||
let headerHeight = 40
|
||||
let footerHeight = 30
|
||||
let listItemHeight = SIDE_PANEL_WIDTH * 0.75
|
||||
|
||||
let posibleVisibleListItems
|
||||
|
||||
let itemSeparation
|
||||
|
||||
let onMouseWheelEventSuscriptionId
|
||||
|
||||
return thisObject
|
||||
|
||||
function finalize () {
|
||||
thisObject.container.eventHandler.stopListening(onMouseWheelEventSuscriptionId)
|
||||
|
||||
listItemsMap = undefined
|
||||
visibleListItems = undefined
|
||||
|
||||
thisObject.container.finalize()
|
||||
thisObject.container = undefined
|
||||
|
||||
thisObject.payload = undefined
|
||||
thisObject = undefined
|
||||
}
|
||||
|
||||
function initialize () {
|
||||
thisObject.container.name = MODULE_NAME
|
||||
thisObject.container.frame.containerName = thisObject.container.name
|
||||
thisObject.container.frame.width = SIDE_PANEL_WIDTH * 0.75
|
||||
|
||||
let position = { // Default position
|
||||
x: SIDE_PANEL_WIDTH * 0.25 / 2,
|
||||
y: 20
|
||||
}
|
||||
|
||||
thisObject.container.frame.position = position
|
||||
|
||||
onMouseWheelEventSuscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseWheel', onMouseWheel)
|
||||
|
||||
resize()
|
||||
turnOn()
|
||||
}
|
||||
|
||||
function resize () {
|
||||
thisObject.container.frame.height = browserCanvas.height - thisObject.container.frame.position.y * 2
|
||||
|
||||
let spaceForListItems = (thisObject.container.frame.height - headerHeight - footerHeight)
|
||||
posibleVisibleListItems = Math.trunc(spaceForListItems / (listItemHeight))
|
||||
if ((posibleVisibleListItems - 1) !== 0) {
|
||||
itemSeparation = (spaceForListItems - listItemHeight * posibleVisibleListItems) / (posibleVisibleListItems - 1)
|
||||
} else {
|
||||
itemSeparation = 0
|
||||
}
|
||||
}
|
||||
|
||||
function turnOn () {
|
||||
firstVisibleListItem = 1
|
||||
|
||||
callServer(undefined, 'ListWorkspaces', onResponse)
|
||||
|
||||
function onResponse (err, text) {
|
||||
if (err && err.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) {
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] initialize -> Could not load the list of your workspaces from the backend. ') }
|
||||
return
|
||||
}
|
||||
|
||||
let workspacelist = JSON.parse(text)
|
||||
thisObject.listItems = []
|
||||
for (let i = 0; i < workspacelist.length; i++) {
|
||||
let workspace = workspacelist[i].replace('.json', '')
|
||||
let listItem = newListItem()
|
||||
listItem.initialize(workspace, 'Workspace')
|
||||
listItem.container.connectToParent(thisObject.container, false, false)
|
||||
|
||||
thisObject.listItems.push(listItem)
|
||||
}
|
||||
calculateVisbleListItems()
|
||||
isInitialized = true
|
||||
thisObject.isVisible = true
|
||||
}
|
||||
}
|
||||
|
||||
function turnOff () {
|
||||
thisObject.isVisible = false
|
||||
}
|
||||
|
||||
function onMouseWheel (event) {
|
||||
delta = event.wheelDelta
|
||||
if (delta > 0) {
|
||||
delta = -1
|
||||
} else {
|
||||
delta = 1
|
||||
}
|
||||
|
||||
firstVisibleListItem = firstVisibleListItem + delta
|
||||
|
||||
calculateVisbleListItems()
|
||||
}
|
||||
|
||||
function calculateVisbleListItems () {
|
||||
let availableSlots = Math.trunc(posibleVisibleListItems)
|
||||
|
||||
if (firstVisibleListItem < 1) { firstVisibleListItem = 1 }
|
||||
if (firstVisibleListItem > (thisObject.listItems.length - availableSlots + 1)) { firstVisibleListItem = thisObject.listItems.length - availableSlots + 1 }
|
||||
|
||||
visibleListItems = []
|
||||
|
||||
for (let i = 0; i < thisObject.listItems.length; i++) {
|
||||
if (i + 1 >= firstVisibleListItem && i + 1 < firstVisibleListItem + availableSlots) {
|
||||
let listItem = thisObject.listItems[i]
|
||||
|
||||
listItem.container.frame.position.x = 0
|
||||
listItem.container.frame.position.y = (listItemHeight + itemSeparation) * visibleListItems.length + headerHeight
|
||||
|
||||
/* Add to Visible Product Array */
|
||||
visibleListItems.push(listItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getContainer (point, purpose) {
|
||||
if (isInitialized === false || thisObject.isVisible === false) { return }
|
||||
let container
|
||||
|
||||
/* First we check if thisObject point is inside thisObject space. */
|
||||
if (thisObject.container.frame.isThisPointHere(point, true) === true) {
|
||||
/* Now we see which is the inner most container that has it */
|
||||
for (let i = 0; i < visibleListItems.length; i++) {
|
||||
container = visibleListItems[i].getContainer(point)
|
||||
|
||||
if (container !== undefined) {
|
||||
if (container.isForThisPurpose(purpose) === true) {
|
||||
return container
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return thisObject.container
|
||||
}
|
||||
}
|
||||
|
||||
function childrenPhysics () {
|
||||
for (let i = 0; i < thisObject.listItems.length; i++) {
|
||||
let listItem = thisObject.listItems[i]
|
||||
listItem.physics()
|
||||
}
|
||||
}
|
||||
|
||||
function physics () {
|
||||
if (isInitialized === false || thisObject.isVisible === false) { return }
|
||||
if (isInitialized === false) { return }
|
||||
if (thisObject.isVisible === false) { return }
|
||||
childrenPhysics()
|
||||
}
|
||||
|
||||
function draw () {
|
||||
if (isInitialized === false || thisObject.isVisible === false) { return }
|
||||
|
||||
drawBackground()
|
||||
drawChildren()
|
||||
drawScrollBar()
|
||||
}
|
||||
|
||||
function drawChildren () {
|
||||
for (let i = 0; i < visibleListItems.length; i++) {
|
||||
let listItem = visibleListItems[i]
|
||||
if (listItem !== undefined) {
|
||||
listItem.draw()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function drawBackground () {
|
||||
let label = 'Your Workspaces'
|
||||
|
||||
let backgroundColor = UI_COLOR.WHITE
|
||||
let params = {
|
||||
cornerRadius: 5,
|
||||
lineWidth: 1,
|
||||
container: thisObject.container,
|
||||
borderColor: UI_COLOR.RUSTED_RED,
|
||||
castShadow: false,
|
||||
backgroundColor: backgroundColor,
|
||||
opacity: 1
|
||||
}
|
||||
|
||||
roundedCornersBackground(params)
|
||||
|
||||
drawLabel(label, 1 / 2, 0, 0, 25, 15, thisObject.container, UI_COLOR.BLACK)
|
||||
}
|
||||
|
||||
function drawScrollBar () {
|
||||
if (thisObject.listItems.length > posibleVisibleListItems && posibleVisibleListItems > 0) {
|
||||
let xOffset = 4
|
||||
let barTopPoint = {
|
||||
x: thisObject.container.frame.width - xOffset,
|
||||
y: headerHeight
|
||||
}
|
||||
let barBottomPoint = {
|
||||
x: thisObject.container.frame.width - xOffset,
|
||||
y: thisObject.container.frame.height - footerHeight
|
||||
}
|
||||
let ratio = (posibleVisibleListItems * listItemHeight + (posibleVisibleListItems - 1) * itemSeparation) / (thisObject.listItems.length * listItemHeight + (thisObject.listItems.length - 1) * itemSeparation)
|
||||
let handleHeight = posibleVisibleListItems * (listItemHeight * ratio) + (posibleVisibleListItems - 1) * itemSeparation * ratio
|
||||
let handleTopPoint = {
|
||||
x: thisObject.container.frame.width - xOffset,
|
||||
y: headerHeight + (listItemHeight * ratio * (firstVisibleListItem - 1) + itemSeparation * ratio * (firstVisibleListItem - 1))
|
||||
}
|
||||
let handleBottomPoint = {
|
||||
x: thisObject.container.frame.width - xOffset,
|
||||
y: handleTopPoint.y + handleHeight
|
||||
}
|
||||
barTopPoint = thisObject.container.frame.frameThisPoint(barTopPoint)
|
||||
barBottomPoint = thisObject.container.frame.frameThisPoint(barBottomPoint)
|
||||
handleTopPoint = thisObject.container.frame.frameThisPoint(handleTopPoint)
|
||||
handleBottomPoint = thisObject.container.frame.frameThisPoint(handleBottomPoint)
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.moveTo(barTopPoint.x, barTopPoint.y)
|
||||
browserCanvasContext.lineTo(barBottomPoint.x, barBottomPoint.y)
|
||||
browserCanvasContext.closePath()
|
||||
browserCanvasContext.setLineDash([0, 0])
|
||||
browserCanvasContext.lineWidth = 1
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.GREY + ', ' + 1 + ')'
|
||||
browserCanvasContext.stroke()
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.moveTo(handleTopPoint.x, handleTopPoint.y)
|
||||
browserCanvasContext.lineTo(handleBottomPoint.x, handleBottomPoint.y)
|
||||
browserCanvasContext.closePath()
|
||||
browserCanvasContext.setLineDash([0, 0])
|
||||
browserCanvasContext.lineWidth = 4
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.PATINATED_TURQUOISE + ', ' + 1 + ')'
|
||||
browserCanvasContext.stroke()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,8 @@ function newSidePanelTab () {
|
||||
let thisObject = {
|
||||
pointerDirection: 'left',
|
||||
container: undefined,
|
||||
resize: resize,
|
||||
physics: physics,
|
||||
draw: draw,
|
||||
getContainer: getContainer,
|
||||
initialize: initialize
|
||||
@@ -27,20 +29,27 @@ function newSidePanelTab () {
|
||||
function initialize () {
|
||||
thisObject.container.frame.width = TAB_WIDTH
|
||||
thisObject.container.frame.height = TAB_HEIGHT
|
||||
thisObject.container.frame.position.x = 0 + thisObject.container.parentContainer.frame.width
|
||||
thisObject.container.frame.position.y = 20
|
||||
|
||||
ORIGINAL_PARENT_POSITON = thisObject.container.parentContainer.frame.position.x
|
||||
|
||||
thisObject.container.eventHandler.listenToEvent('onMouseClick', onMouseClick)
|
||||
resize()
|
||||
isInitialized = true
|
||||
}
|
||||
|
||||
function resize () {
|
||||
thisObject.container.frame.position.x = 0 + thisObject.container.parentContainer.frame.width
|
||||
thisObject.container.frame.position.y = 69
|
||||
setClosed()
|
||||
}
|
||||
|
||||
function onMouseClick (event) {
|
||||
if (thisObject.pointerDirection === 'left') {
|
||||
animation = 'opening'
|
||||
thisObject.container.eventHandler.raiseEvent('opening')
|
||||
} else {
|
||||
animation = 'closing'
|
||||
thisObject.container.eventHandler.raiseEvent('closing')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,9 +62,13 @@ function newSidePanelTab () {
|
||||
}
|
||||
}
|
||||
|
||||
function draw () {
|
||||
function physics () {
|
||||
if (isInitialized === false) { return }
|
||||
animate()
|
||||
}
|
||||
|
||||
function draw () {
|
||||
if (isInitialized === false) { return }
|
||||
borders()
|
||||
arrow()
|
||||
}
|
||||
@@ -66,28 +79,37 @@ function newSidePanelTab () {
|
||||
if (animation === 'opening') {
|
||||
xOffset = xOffset + STEP
|
||||
thisObject.container.parentContainer.frame.position.x = ORIGINAL_PARENT_POSITON + xOffset
|
||||
if (xOffset > thisObject.container.parentContainer.frame.width) {
|
||||
animation = 'none'
|
||||
xOffset = thisObject.container.parentContainer.frame.width
|
||||
thisObject.container.parentContainer.frame.position.x = ORIGINAL_PARENT_POSITON + xOffset
|
||||
thisObject.container.parentContainer.status = 'visible'
|
||||
thisObject.pointerDirection = 'right'
|
||||
if (xOffset >= thisObject.container.parentContainer.frame.width) {
|
||||
setOpened()
|
||||
thisObject.container.eventHandler.raiseEvent('opened')
|
||||
}
|
||||
}
|
||||
|
||||
if (animation === 'closing') {
|
||||
xOffset = xOffset - STEP
|
||||
thisObject.container.parentContainer.frame.position.x = ORIGINAL_PARENT_POSITON + xOffset
|
||||
if (xOffset < 0) {
|
||||
animation = 'none'
|
||||
xOffset = 0
|
||||
thisObject.container.parentContainer.frame.position.x = ORIGINAL_PARENT_POSITON
|
||||
thisObject.container.parentContainer.status = 'hidden'
|
||||
thisObject.pointerDirection = 'left'
|
||||
if (xOffset <= 0) {
|
||||
setClosed()
|
||||
thisObject.container.eventHandler.raiseEvent('closed')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setOpened () {
|
||||
animation = 'none'
|
||||
xOffset = thisObject.container.parentContainer.frame.width
|
||||
thisObject.container.parentContainer.frame.position.x = ORIGINAL_PARENT_POSITON + xOffset
|
||||
thisObject.container.parentContainer.status = 'visible'
|
||||
thisObject.pointerDirection = 'right'
|
||||
}
|
||||
function setClosed () {
|
||||
animation = 'none'
|
||||
xOffset = 0
|
||||
thisObject.container.parentContainer.frame.position.x = ORIGINAL_PARENT_POSITON
|
||||
thisObject.container.parentContainer.status = 'hidden'
|
||||
thisObject.pointerDirection = 'left'
|
||||
}
|
||||
|
||||
function arrow () {
|
||||
let point1
|
||||
let point2
|
||||
@@ -213,4 +235,3 @@ function newSidePanelTab () {
|
||||
browserCanvasContext.stroke()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,12 +92,16 @@ function newChartingSpace () {
|
||||
|
||||
function initialize () {
|
||||
if (isInitialized === true) { return }
|
||||
if (canvas.designSpace === undefined) { return }
|
||||
if (canvas.designSpace.workspace === undefined) { return }
|
||||
|
||||
let rootNodes = canvas.designSpace.workspace.workspaceNode.rootNodes
|
||||
for (let i = 0; i < rootNodes.length; i++) {
|
||||
let rootNode = rootNodes[i]
|
||||
if (rootNode.type === 'Charting Space') {
|
||||
thisObject.payload = rootNode.payload
|
||||
if (rootNode !== null) {
|
||||
if (rootNode.type === 'Charting Space') {
|
||||
thisObject.payload = rootNode.payload
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,6 +406,7 @@ function newChartingSpace () {
|
||||
}
|
||||
|
||||
function draw () {
|
||||
if (canWeDraw === false) { return }
|
||||
if (thisObject.visible === false) { return }
|
||||
drawBackground()
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
physics: physics,
|
||||
getContainer: getContainer,
|
||||
finalize: finalize,
|
||||
initialize: initialize
|
||||
initialize: initialize,
|
||||
initializePosition: initializePosition
|
||||
}
|
||||
|
||||
thisObject.container = newContainer()
|
||||
@@ -39,6 +40,7 @@
|
||||
let statusCounter = 0
|
||||
let statusText
|
||||
let statusType
|
||||
let isInitilized = false
|
||||
|
||||
return thisObject
|
||||
|
||||
@@ -52,6 +54,15 @@
|
||||
}
|
||||
|
||||
function initialize () {
|
||||
canvasBrowserResizedEventSubscriptionId = canvas.eventHandler.listenToEvent('Browser Resized', resize)
|
||||
selfMouseClickEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseClick', onMouseClick)
|
||||
|
||||
thisObject.fullscreen = newFullScreen()
|
||||
thisObject.fullscreen.container.connectToParent(thisObject.container)
|
||||
thisObject.fullscreen.initialize()
|
||||
}
|
||||
|
||||
function initializePosition () {
|
||||
thisObject.container.frame.position.x = 0
|
||||
|
||||
let INITIAL_POSITION
|
||||
@@ -68,13 +79,7 @@
|
||||
INITIAL_POSITION = 100
|
||||
thisObject.container.frame.position.y = browserCanvas.height * INITIAL_POSITION / 100 - COCKPIT_SPACE_HEIGHT
|
||||
}
|
||||
|
||||
canvasBrowserResizedEventSubscriptionId = canvas.eventHandler.listenToEvent('Browser Resized', resize)
|
||||
selfMouseClickEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseClick', onMouseClick)
|
||||
|
||||
thisObject.fullscreen = newFullScreen()
|
||||
thisObject.fullscreen.container.connectToParent(thisObject.container)
|
||||
thisObject.fullscreen.initialize()
|
||||
isInitilized = true
|
||||
}
|
||||
|
||||
function onMouseClick (event) {
|
||||
@@ -148,6 +153,7 @@
|
||||
thisObject.fullscreen.physics()
|
||||
}
|
||||
function thisObjectPhysics () {
|
||||
if (isInitilized === false) { return }
|
||||
/* Check the limits */
|
||||
|
||||
thisObject.status = 'MIDDLE'
|
||||
@@ -201,6 +207,7 @@
|
||||
}
|
||||
|
||||
function draw () {
|
||||
if (canWeDraw === false) { return }
|
||||
thisObject.container.frame.draw(false, false)
|
||||
|
||||
drawBackground()
|
||||
@@ -266,8 +273,10 @@
|
||||
printLabel(statusText, position.x, position.y, 1, 15, textColor, true, thisObject.container)
|
||||
}
|
||||
|
||||
if (canvas.designSpace.workspace.enabled === true && statusText === undefined) {
|
||||
arrow()
|
||||
if (canvas.designSpace !== undefined) {
|
||||
if (canvas.designSpace.workspace.enabled === true && statusText === undefined) {
|
||||
arrow()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -334,6 +334,7 @@ function newDesignSpace () {
|
||||
}
|
||||
|
||||
function draw () {
|
||||
if (canWeDraw === false) { return }
|
||||
if (thisObject.sidePanel !== undefined) {
|
||||
thisObject.sidePanel.draw()
|
||||
}
|
||||
|
||||
@@ -415,6 +415,7 @@ function newFloatingSpace () {
|
||||
}
|
||||
|
||||
function draw () {
|
||||
if (canWeDraw === false) { return }
|
||||
if (visible === false) { return }
|
||||
drawBackground()
|
||||
thisObject.floatingLayer.draw()
|
||||
|
||||
@@ -336,6 +336,7 @@ function newPanelsSpace () {
|
||||
}
|
||||
|
||||
function draw () {
|
||||
if (canWeDraw === false) { return }
|
||||
if (thisObject.visible !== true) { return }
|
||||
|
||||
thisObject.container.frame.draw(false, false)
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
function newSidePanel () {
|
||||
const MODULE_NAME = 'Side Panel'
|
||||
function newSideSpace () {
|
||||
const MODULE_NAME = 'Side Space'
|
||||
let thisObject = {
|
||||
areas: [],
|
||||
sidePanelTab: undefined,
|
||||
container: undefined,
|
||||
physics: physics,
|
||||
draw: draw,
|
||||
getContainer: getContainer,
|
||||
initialize: initialize
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
}
|
||||
|
||||
let isInitialized = false
|
||||
@@ -16,9 +17,16 @@ function newSidePanel () {
|
||||
thisObject.container.initialize()
|
||||
thisObject.container.isClickeable = true
|
||||
thisObject.container.isDraggeable = false
|
||||
thisObject.container.detectMouseOver = true
|
||||
thisObject.container.status = 'hidden'
|
||||
|
||||
let listView
|
||||
|
||||
resize()
|
||||
|
||||
let openingEventSubscriptionId
|
||||
let closedEventSubscriptionId
|
||||
let browserResizedEventSubscriptionId
|
||||
return thisObject
|
||||
|
||||
function initialize () {
|
||||
@@ -26,21 +34,48 @@ function newSidePanel () {
|
||||
thisObject.sidePanelTab.container.connectToParent(thisObject.container, false, false)
|
||||
thisObject.sidePanelTab.initialize()
|
||||
|
||||
canvas.eventHandler.listenToEvent('Browser Resized', resize)
|
||||
browserResizedEventSubscriptionId = canvas.eventHandler.listenToEvent('Browser Resized', resize)
|
||||
|
||||
initializeListView()
|
||||
isInitialized = true
|
||||
}
|
||||
|
||||
function finalize () {
|
||||
canvas.eventHandler.stopListening(browserResizedEventSubscriptionId)
|
||||
thisObject.sidePanelTab.container.eventHandler.stopListening(openingEventSubscriptionId)
|
||||
thisObject.sidePanelTab.container.eventHandler.stopListening(closedEventSubscriptionId)
|
||||
}
|
||||
|
||||
function initializeListView () {
|
||||
listView = newListView()
|
||||
listView.initialize()
|
||||
listView.container.connectToParent(thisObject.container, false, false)
|
||||
openingEventSubscriptionId = thisObject.sidePanelTab.container.eventHandler.listenToEvent('opening', listView.turnOn)
|
||||
closedEventSubscriptionId = thisObject.sidePanelTab.container.eventHandler.listenToEvent('closed', listView.turnOff)
|
||||
}
|
||||
|
||||
function resize () {
|
||||
thisObject.container.frame.width = SIDE_PANEL_WIDTH
|
||||
thisObject.container.frame.height = browserCanvas.height // - TOP_SPACE_HEIGHT
|
||||
thisObject.container.frame.position.x = -SIDE_PANEL_WIDTH
|
||||
thisObject.container.frame.position.y = 0 // TOP_SPACE_HEIGHT
|
||||
|
||||
if (listView !== undefined) {
|
||||
listView.resize()
|
||||
}
|
||||
|
||||
if (thisObject.sidePanelTab !== undefined) {
|
||||
thisObject.sidePanelTab.resize()
|
||||
}
|
||||
}
|
||||
|
||||
function getContainer (point) {
|
||||
function getContainer (point, purpose) {
|
||||
let container
|
||||
|
||||
container = thisObject.sidePanelTab.getContainer(point)
|
||||
container = thisObject.sidePanelTab.getContainer(point, purpose)
|
||||
if (container !== undefined) { return container }
|
||||
|
||||
container = listView.getContainer(point, purpose)
|
||||
if (container !== undefined) { return container }
|
||||
|
||||
if (thisObject.container.frame.isThisPointHere(point, true) === true) {
|
||||
@@ -50,15 +85,17 @@ function newSidePanel () {
|
||||
}
|
||||
}
|
||||
|
||||
function physics () {
|
||||
thisObject.sidePanelTab.physics()
|
||||
listView.physics()
|
||||
}
|
||||
|
||||
function draw () {
|
||||
if (canWeDraw === false) { return }
|
||||
if (isInitialized === false) { return }
|
||||
borders()
|
||||
thisObject.sidePanelTab.draw()
|
||||
|
||||
for (let i = 0; i < thisObject.areas.length; i++) {
|
||||
let area = thisObject.areas[i]
|
||||
area.draw()
|
||||
}
|
||||
listView.draw()
|
||||
}
|
||||
|
||||
function borders () {
|
||||
@@ -54,6 +54,7 @@ function newTopSpace () {
|
||||
}
|
||||
|
||||
function draw () {
|
||||
if (canWeDraw === false) { return }
|
||||
thisObject.container.frame.draw(false, false)
|
||||
|
||||
drawBackground()
|
||||
@@ -65,7 +66,7 @@ function newTopSpace () {
|
||||
let opacity = 1
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.rect(0, 0, thisObject.container.frame.width, thisObject.container.frame.height)
|
||||
if (areWeRecording === true) {
|
||||
if (ARE_WE_RECORDING_A_VIDEO === true) {
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.PATINATED_TURQUOISE + ', ' + opacity + ')'
|
||||
} else {
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.RUSTED_RED + ', ' + opacity + ')'
|
||||
|
||||
@@ -13,7 +13,7 @@ function newSplashScreen () {
|
||||
initialize: initialize
|
||||
}
|
||||
|
||||
var container = newContainer()
|
||||
let container = newContainer()
|
||||
container.initialize()
|
||||
thisObject.container = container
|
||||
|
||||
@@ -31,21 +31,22 @@ function newSplashScreen () {
|
||||
|
||||
let logo
|
||||
let canDrawLogo = false
|
||||
let isInitialized = false
|
||||
let splashScreenNeeded = true
|
||||
|
||||
return thisObject
|
||||
|
||||
function initialize () {
|
||||
logo = new Image()
|
||||
|
||||
logo.onload = onImageLoad
|
||||
|
||||
function onImageLoad () {
|
||||
canDrawLogo = true
|
||||
}
|
||||
|
||||
logo.src = window.canvasApp.urlPrefix + 'Images/superalgos-logo.png'
|
||||
|
||||
canvas.eventHandler.listenToEvent('Browser Resized', resize)
|
||||
|
||||
isInitialized = true
|
||||
}
|
||||
|
||||
function resize () {
|
||||
@@ -54,6 +55,7 @@ function newSplashScreen () {
|
||||
}
|
||||
|
||||
function draw () {
|
||||
if (isInitialized === false) { return }
|
||||
if (splashScreenNeeded === false) {
|
||||
stepsInitializationCounter = 100
|
||||
canDrawLogo = false
|
||||
@@ -101,6 +103,7 @@ function newSplashScreen () {
|
||||
|
||||
if (stepsInitializationCounter > 99) {
|
||||
splashScreenNeeded = false
|
||||
canWeDraw = true
|
||||
stepsInitializationCounter = 99
|
||||
}
|
||||
|
||||
@@ -122,7 +125,7 @@ function newSplashScreen () {
|
||||
|
||||
fontSize = 35
|
||||
|
||||
title = 'Beta 4'
|
||||
title = 'Beta 5'
|
||||
|
||||
titlePoint = {
|
||||
x: thisObject.container.frame.width / 2 - title.length / 2 * fontSize * FONT_ASPECT_RATIO - 20,
|
||||
|
||||
+34
-2
@@ -108,8 +108,8 @@ function downloadText (filename, text) {
|
||||
document.body.removeChild(element)
|
||||
}
|
||||
|
||||
function downloadCanvas (filename) {
|
||||
let data = browserCanvas.toDataURL('image/png', 1)
|
||||
function downloadCanvas (filename, canvasToUse) {
|
||||
let data = canvasToUse.toDataURL('image/png', 1)
|
||||
/* Change MIME type to trick the browser to downlaod the file instead of displaying it */
|
||||
data = data.replace(/^data:image\/[^;]*/, 'data:application/octet-stream')
|
||||
|
||||
@@ -125,6 +125,38 @@ function downloadCanvas (filename) {
|
||||
document.body.removeChild(element)
|
||||
};
|
||||
|
||||
function downloadPanorama (filename) {
|
||||
let INITIAL_WIDTH = 800
|
||||
let FINAL_WIDTH = browserCanvas.width - INITIAL_WIDTH
|
||||
|
||||
if (ARE_WE_RECORDING_A_MARKET_PANORAMA === false) {
|
||||
/* We start recording the panorame. */
|
||||
ARE_WE_RECORDING_A_MARKET_PANORAMA = true
|
||||
marketPanoramaCanvas = document.createElement('canvas')
|
||||
marketPanoramaCanvas.width = INITIAL_WIDTH * 50
|
||||
marketPanoramaCanvas.height = browserCanvas.height
|
||||
marketPanoramaCanvas.getContext('2d').drawImage(browserCanvas, 0, 0, INITIAL_WIDTH, browserCanvas.height, 0, 0, INITIAL_WIDTH, browserCanvas.height)
|
||||
CURRENT_PANORAMA_POSITION = INITIAL_WIDTH
|
||||
} else {
|
||||
/* We stop recording and download the resulting image. */
|
||||
ARE_WE_RECORDING_A_MARKET_PANORAMA = false
|
||||
marketPanoramaCanvas.getContext('2d').drawImage(browserCanvas, browserCanvas.width - FINAL_WIDTH, 0, FINAL_WIDTH, browserCanvas.height, CURRENT_PANORAMA_POSITION, 0, FINAL_WIDTH, browserCanvas.height)
|
||||
let finalResultCanvas = document.createElement('canvas')
|
||||
finalResultCanvas.width = CURRENT_PANORAMA_POSITION + FINAL_WIDTH
|
||||
finalResultCanvas.height = browserCanvas.height
|
||||
finalResultCanvas.getContext('2d').drawImage(marketPanoramaCanvas, 0, 0, finalResultCanvas.width, browserCanvas.height, 0, 0, finalResultCanvas.width, browserCanvas.height)
|
||||
downloadCanvas(filename, finalResultCanvas)
|
||||
marketPanoramaCanvas = undefined
|
||||
}
|
||||
}
|
||||
|
||||
function addToMarketPanorama () {
|
||||
let SECTION_WIDTH = 80 * 2
|
||||
let INITIAL_POSITION = 800 - SECTION_WIDTH
|
||||
marketPanoramaCanvas.getContext('2d').drawImage(browserCanvas, INITIAL_POSITION, 0, SECTION_WIDTH, browserCanvas.height, CURRENT_PANORAMA_POSITION, 0, SECTION_WIDTH, browserCanvas.height)
|
||||
CURRENT_PANORAMA_POSITION = CURRENT_PANORAMA_POSITION + SECTION_WIDTH
|
||||
}
|
||||
|
||||
function transformThisPoint (point, container) {
|
||||
/* We make the point relative to the current frame */
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"type":"Data Mine","name":"Masters","code":"{\n\"codeName\": \"Masters\"\n}","sensorBots":[{"type":"Sensor Bot","name":"Exchange Raw Data","code":"{\n\"codeName\": \"Exchange-Raw-Data\",\n\"repo\": \"Exchange-Raw-Data-Sensor-Bot\"\n}","processes":[{"type":"Process Definition","name":"Historic-Trades","code":"{\n \"codeName\": \"Historic-Trades\",\n \"description\": \"Retrieves and saves the historical trades in batches going backwards from the current time until reaching the begining of the market.\",\n \"startMode\": {\n \"noTime\": {\n \"run\": \"true\"\n },\n \"fixedInterval\": {\n \"run\": \"false\",\n \"interval\": 0\n }\n },\n \"deadWaitTime\": 0,\n \"normalWaitTime\": 60000,\n \"retryWaitTime\": 10000\n}","processOutput":{"type":"Process Output","name":"New Process Output","outputDatasets":[],"id":"e3008f15-43ae-4452-9c28-bfbb6c1a5e84","savedPayload":{"position":{"x":13889.892304785908,"y":17976.7326423862},"targetPosition":{"x":13788.99537092664,"y":18353.285125876908},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":4,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","statusDependencies":[{"type":"Status Dependency","name":"Self Reference","code":"{\n \"mainUtility\": \"Self Reference\"\n}","id":"f796022a-7871-4bde-bcc7-bcf2818f1eaf","savedPayload":{"position":{"x":14299.325525762739,"y":17993.12379366583},"targetPosition":{"x":13938.17907937083,"y":17993.12379366583},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"116834de-6646-4387-9f4b-4f711cea9235"}}}],"dataDependencies":[],"id":"1332b41e-7cd2-4e69-a40a-39ea47df67b5","savedPayload":{"position":{"x":13938.17907937083,"y":17993.12379366583},"targetPosition":{"x":13788.99537092664,"y":18353.285125876908},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":4,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","id":"116834de-6646-4387-9f4b-4f711cea9235","savedPayload":{"position":{"x":13983.913279342734,"y":18015.677405195172},"targetPosition":{"x":13788.99537092664,"y":18353.285125876908},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":4,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"New Execution Started Event","id":"a9ea7169-fcd8-48c3-b0a9-b4e8941aa170","savedPayload":{"position":{"x":14026.312379860185,"y":18044.00757842793},"targetPosition":{"x":13788.99537092664,"y":18353.285125876908},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":4,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"51908884-c7a2-46ca-8a55-209070ae5fa6","savedPayload":{"position":{"x":14064.650920558077,"y":18077.62957624547},"targetPosition":{"x":13788.99537092664,"y":18353.285125876908},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":4,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"7a6a9399-474f-4a93-bcbd-28a594ef1943","savedPayload":{"position":{"x":14351.93363503598,"y":18425.400341491753},"targetPosition":{"x":13888.04337325749,"y":18696.024787447222},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Process Definition","name":"Historic-OHLCVs","code":"{\n \"codeName\": \"Historic-OHLCVs\",\n \"description\": \"Retrieves and saves historical maket data\",\n \"startMode\": {\n \"noTime\": {\n \"run\": \"true\"\n },\n \"fixedInterval\": {\n \"run\": \"false\",\n \"interval\": 0\n }\n },\n \"deadWaitTime\": 0,\n \"normalWaitTime\": 60000,\n \"retryWaitTime\": 10000\n}","processOutput":{"type":"Process Output","name":"New Process Output","outputDatasets":[],"id":"dfe2556e-a765-4e38-9d30-7f91090c0069","savedPayload":{"position":{"x":14546.018334597831,"y":18039.39680205973},"targetPosition":{"x":14407.127481538195,"y":18558.43550715096},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","statusDependencies":[{"type":"Status Dependency","name":"Exchange Raw Data Historic-OHLCVs","code":"{\n \"mainUtility\": \"Self ReferencLine truncated
|
||||
{"type":"Data Mine","name":"Masters","code":"{\n\"codeName\": \"Masters\"\n}","sensorBots":[{"type":"Sensor Bot","name":"Exchange Raw Data","code":"{\n\"codeName\": \"Exchange-Raw-Data\",\n\"repo\": \"Exchange-Raw-Data-Sensor-Bot\"\n}","processes":[{"type":"Process Definition","name":"Historic-Trades","code":"{\n \"codeName\": \"Historic-Trades\",\n \"description\": \"Retrieves and saves the historical trades in batches going backwards from the current time until reaching the begining of the market.\",\n \"startMode\": {\n \"noTime\": {\n \"run\": \"true\"\n },\n \"fixedInterval\": {\n \"run\": \"false\",\n \"interval\": 0\n }\n },\n \"deadWaitTime\": 0,\n \"normalWaitTime\": 60000,\n \"retryWaitTime\": 10000\n}","processOutput":{"type":"Process Output","name":"New Process Output","outputDatasets":[],"id":"e3008f15-43ae-4452-9c28-bfbb6c1a5e84","savedPayload":{"position":{"x":13889.892304785908,"y":17976.7326423862},"targetPosition":{"x":13788.99537092664,"y":18353.285125876908},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":4,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","statusDependencies":[{"type":"Status Dependency","name":"Self Reference","code":"{\n \"mainUtility\": \"Self Reference\"\n}","id":"f796022a-7871-4bde-bcc7-bcf2818f1eaf","savedPayload":{"position":{"x":14299.325525762739,"y":17993.12379366583},"targetPosition":{"x":13938.17907937083,"y":17993.12379366583},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Status Report","name":"New Status Report","id":"116834de-6646-4387-9f4b-4f711cea9235"}}}],"dataDependencies":[],"id":"1332b41e-7cd2-4e69-a40a-39ea47df67b5","savedPayload":{"position":{"x":13938.17907937083,"y":17993.12379366583},"targetPosition":{"x":13788.99537092664,"y":18353.285125876908},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":4,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"statusReport":{"type":"Status Report","name":"New Status Report","id":"116834de-6646-4387-9f4b-4f711cea9235","savedPayload":{"position":{"x":13983.913279342734,"y":18015.677405195172},"targetPosition":{"x":13788.99537092664,"y":18353.285125876908},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":4,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionStartedEvent":{"type":"Execution Started Event","name":"New Execution Started Event","id":"a9ea7169-fcd8-48c3-b0a9-b4e8941aa170","savedPayload":{"position":{"x":14026.312379860185,"y":18044.00757842793},"targetPosition":{"x":13788.99537092664,"y":18353.285125876908},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":4,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"executionFinishedEvent":{"type":"Execution Finished Event","name":"New Execution Finished Event","id":"51908884-c7a2-46ca-8a55-209070ae5fa6","savedPayload":{"position":{"x":14064.650920558077,"y":18077.62957624547},"targetPosition":{"x":13788.99537092664,"y":18353.285125876908},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":4,"distanceToParent":3,"arrangementStyle":0},"uiObject":{}}},"id":"7a6a9399-474f-4a93-bcbd-28a594ef1943","savedPayload":{"position":{"x":14351.93363503598,"y":18425.400341491753},"targetPosition":{"x":13888.04337325749,"y":18696.024787447222},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":3,"distanceToParent":2,"arrangementStyle":0},"uiObject":{"isRunning":false}}},{"type":"Process Definition","name":"Historic-OHLCVs","code":"{\n \"codeName\": \"Historic-OHLCVs\",\n \"description\": \"Retrieves and saves historical maket data\",\n \"startMode\": {\n \"noTime\": {\n \"run\": \"true\"\n },\n \"fixedInterval\": {\n \"run\": \"false\",\n \"interval\": 0\n }\n },\n \"deadWaitTime\": 0,\n \"normalWaitTime\": 60000,\n \"retryWaitTime\": 10000\n}","processOutput":{"type":"Process Output","name":"New Process Output","outputDatasets":[],"id":"dfe2556e-a765-4e38-9d30-7f91090c0069","savedPayload":{"position":{"x":14546.018334597831,"y":18039.39680205973},"targetPosition":{"x":14407.127481538195,"y":18558.43550715096},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false}}},"processDependencies":{"type":"Process Dependencies","name":"New Process Dependencies","statusDependencies":[{"type":"Status Dependency","name":"Exchange Raw Data Historic-OHLCVs","code":"{\n \"mainUtility\": \"Self ReferencLine truncated
|
||||
@@ -1 +1 @@
|
||||
{"type":"Data Mine","name":"Trading Engines","code":"{ \n\"codeName\": \"TradingEngines\"\n}","sensorBots":[],"tradingBots":[{"type":"Trading Bot","name":"Protocol Engine","code":"{\n\"codeName\": \"Protocol-Engine\",\n\"repo\": \"Protocol-Engine-Trading-Bot\"\n}","processes":[{"type":"Process Definition","name":"Multi-Period","code":"{\n \"codeName\": \"Multi-Period\",\n \"startMode\": {\n \"userDefined\": {\n \"run\": \"true\"\n }\n },\n \"deadWaitTime\": 0,\n \"liveWaitTime\": 60000,\n \"normalWaitTime\": 5000,\n \"retryWaitTime\": 10000,\n \"sleepWaitTime\": 3600000,\n \"comaWaitTime\": 86400000,\n \"framework\": {\n \"name\": \"Multi-Period\",\n \"validPeriods\": [\n \"45-min\",\n \"40-min\",\n \"30-min\",\n \"20-min\",\n \"15-min\",\n \"10-min\",\n \"05-min\",\n \"04-min\",\n \"03-min\",\n \"02-min\",\n \"01-min\"\n ],\n \"startDate\": {},\n \"endDate\": {}\n }\n}","processOutput":{"type":"Process Output","name":"New Process Output","outputDatasets":[{"type":"Output Dataset","name":"New Output Dataset","id":"2448e10f-8851-4f99-bbc3-4114045de8c0","savedPayload":{"position":{"x":12616.197483671245,"y":20140.853579740375},"targetPosition":{"x":11869.94158089557,"y":20140.853579740375},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"d7335089-1f50-4d48-bcbe-115136a88e6a"}}},{"type":"Output Dataset","name":"New Output Dataset","id":"d1b73084-294b-46f5-a2c4-da08b994b770","savedPayload":{"position":{"x":12449.156688273564,"y":20626.87276271356},"targetPosition":{"x":11869.94158089557,"y":20140.853579740375},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"274082a4-1695-4e9b-a0ff-9464fa2d986f"}}},{"type":"Output Dataset","name":"New Output Dataset","id":"156aa7e6-0514-465e-9734-3983a51ab69c","savedPayload":{"position":{"x":11997.878022585815,"y":20866.417195564853},"targetPosition":{"x":11869.94158089557,"y":20140.853579740375},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"52f26c43-552c-4557-af7a-878b951f5731"}}},{"type":"Output Dataset","name":"New Output Dataset","id":"8067fbac-fbc3-4712-9c24-4b4b9a24d78d","savedPayload":{"position":{"x":11497.788898746769,"y":20785.44093339513},"targetPosition":{"x":11869.94158089557,"y":20140.853579740375},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"afb38dc6-0437-4215-8a7d-3091cd3c74fb"}}},{"type":"Output Dataset","name":"New Output Dataset","id":"72529350-c20e-4f28-a308-2611df7a6468","savedPayload":{"position":{"x":11151.505147800972,"y":20402.34305659919},"targetPosition":{"x":11869.94158089557,"y":20140.853579740375},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"cb317eb0-047c-4076-bd46-7add2423aa87"}}},{"type":"Output Dataset","name":"New Output Dataset","id":"1b491b01-465a-4f98-831d-a587fc428b58","savedPayload":{"position":{"x":11191.18832670422,"y":19893.807598803403},"targetPosition":{"x":11869.94158089557,"y":20140.853579740375},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"41498979-9228-4151-8b94-0d8acdf257e8"}}},{"type":"Output Dataset","name":"New Output Dataset","id":"5711ecc2-5192-4d97-a13d-5269264ea825","savedPayload":{"position":{"x":11500.627966186497,"y":19501.183635137346},"targetPosition":{"x":11869.94158089557,"y":20140.853579740375},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"823a30de-093f-4c39-9181-5727c81bbad3"}}},{"type":"Output Dataset","name":"New Output Dataset","id":"3be12bcb-4634-4933-9ae1-bad5089b8062","savedPayload":{"position":{"x":12002.767486869507,"y":19387.560434016126},"targetPosition":{"x":11869.94158089557,"y":20140.853579740375},"floatingObject":{"isPinned":false,"isFrozeLine truncated
|
||||
{"type":"Data Mine","name":"Trading Engines","code":"{ \n\"codeName\": \"TradingEngines\"\n}","sensorBots":[],"indicatorBots":[],"tradingBots":[{"type":"Trading Bot","name":"Protocol Engine","code":"{\n\"codeName\": \"Protocol-Engine\",\n\"repo\": \"Protocol-Engine-Trading-Bot\"\n}","processes":[{"type":"Process Definition","name":"Multi-Period","code":"{\n \"codeName\": \"Multi-Period\",\n \"startMode\": {\n \"userDefined\": {\n \"run\": \"true\"\n }\n },\n \"deadWaitTime\": 0,\n \"liveWaitTime\": 60000,\n \"normalWaitTime\": 5000,\n \"retryWaitTime\": 10000,\n \"sleepWaitTime\": 3600000,\n \"comaWaitTime\": 86400000,\n \"framework\": {\n \"name\": \"Multi-Period\",\n \"validPeriods\": [\n \"45-min\",\n \"40-min\",\n \"30-min\",\n \"20-min\",\n \"15-min\",\n \"10-min\",\n \"05-min\",\n \"04-min\",\n \"03-min\",\n \"02-min\",\n \"01-min\"\n ],\n \"startDate\": {},\n \"endDate\": {}\n }\n}","processOutput":{"type":"Process Output","name":"New Process Output","outputDatasets":[{"type":"Output Dataset","name":"New Output Dataset","id":"2448e10f-8851-4f99-bbc3-4114045de8c0","savedPayload":{"position":{"x":12616.197483671245,"y":20140.853579740375},"targetPosition":{"x":11869.94158089557,"y":20140.853579740375},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"d7335089-1f50-4d48-bcbe-115136a88e6a"}}},{"type":"Output Dataset","name":"New Output Dataset","id":"d1b73084-294b-46f5-a2c4-da08b994b770","savedPayload":{"position":{"x":12449.156688273564,"y":20626.87276271356},"targetPosition":{"x":11869.94158089557,"y":20140.853579740375},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"274082a4-1695-4e9b-a0ff-9464fa2d986f"}}},{"type":"Output Dataset","name":"New Output Dataset","id":"156aa7e6-0514-465e-9734-3983a51ab69c","savedPayload":{"position":{"x":11997.878022585815,"y":20866.417195564853},"targetPosition":{"x":11869.94158089557,"y":20140.853579740375},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"52f26c43-552c-4557-af7a-878b951f5731"}}},{"type":"Output Dataset","name":"New Output Dataset","id":"8067fbac-fbc3-4712-9c24-4b4b9a24d78d","savedPayload":{"position":{"x":11497.788898746769,"y":20785.44093339513},"targetPosition":{"x":11869.94158089557,"y":20140.853579740375},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"afb38dc6-0437-4215-8a7d-3091cd3c74fb"}}},{"type":"Output Dataset","name":"New Output Dataset","id":"72529350-c20e-4f28-a308-2611df7a6468","savedPayload":{"position":{"x":11151.505147800972,"y":20402.34305659919},"targetPosition":{"x":11869.94158089557,"y":20140.853579740375},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"cb317eb0-047c-4076-bd46-7add2423aa87"}}},{"type":"Output Dataset","name":"New Output Dataset","id":"1b491b01-465a-4f98-831d-a587fc428b58","savedPayload":{"position":{"x":11191.18832670422,"y":19893.807598803403},"targetPosition":{"x":11869.94158089557,"y":20140.853579740375},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Daily","id":"41498979-9228-4151-8b94-0d8acdf257e8"}}},{"type":"Output Dataset","name":"New Output Dataset","id":"5711ecc2-5192-4d97-a13d-5269264ea825","savedPayload":{"position":{"x":11500.627966186497,"y":19501.183635137346},"targetPosition":{"x":11869.94158089557,"y":20140.853579740375},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":1,"distanceToParent":3,"arrangementStyle":0},"uiObject":{},"referenceParent":{"type":"Dataset Definition","name":"Multi-Period-Market","id":"823a30de-093f-4c39-9181-5727c81bbad3"}}},{"type":"Output Dataset","name":"New Output Dataset","id":"3be12bcb-4634-4933-9ae1-bad5089b8062","savedPayload":{"position":{"x":12002.767486869507,"y":19387.560434016126},"targetPosition":{"x":11869.94158089557,"y":20140.853579740375},"floatingObject":{"isPinLine truncated
|
||||
@@ -384,6 +384,7 @@
|
||||
record.beginRate = dailyFile[i][4];
|
||||
record.endRate = dailyFile[i][5];
|
||||
record.triggerOnSituation = dailyFile[i][6];
|
||||
record.name = dailyFile[i][7];
|
||||
|
||||
if (
|
||||
(record.begin >= farLeftDate.valueOf() && record.end <= farRightDate.valueOf()) &&
|
||||
@@ -456,6 +457,7 @@
|
||||
record.beginRate = marketFile[i][4];
|
||||
record.endRate = marketFile[i][5];
|
||||
record.triggerOnSituation = marketFile[i][6];
|
||||
record.name = marketFile[i][7];
|
||||
|
||||
if (record.begin >= leftDate.valueOf() && record.end <= rightDate.valueOf()) {
|
||||
|
||||
@@ -581,7 +583,11 @@
|
||||
/* Situation Name */
|
||||
let digit = record.begin.toFixed(0).substring(7,8)
|
||||
let positionY = recordPoint3.y - (recordPoint3.y - recordPoint1.y) / 2 + (Number(digit) * 10 - 50)
|
||||
|
||||
if (canvas.chartingSpace.viewport.zoomLevel >= ZOOM_OUT_THRESHOLD_FOR_HIDDING_CHARTS_LABELS) {
|
||||
if (record.name !== "New Strategy") {
|
||||
printLabel(record.name, recordPoint1.x + 5, positionY - 15, '1', 12);
|
||||
}
|
||||
if (record.triggerOnSituation !== "New Situation") {
|
||||
printLabel(record.triggerOnSituation, recordPoint1.x + 5, positionY, '1', 12);
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
{"type":"Workspace","name":"Binance - WHB - BBTB","rootNodes":[{"type":"Network","name":"Superalgos","networkNodes":[{"type":"Network Node","name":"My Computer","code":"{ \n\"host\": \"localhost\", \n\"webPort\": \"34247\", \n\"webSocketsPort\": \"8080\"\n}","dataStorage":{"type":"Data Storage","name":"New Data Storage","sessionIndependentData":{"type":"Session Independent Data","name":"New Session Independent Data","exchangeDataProducts":[{"type":"Exchange Data Products","name":"Binance","singleMarketData":[{"type":"Single Market Data","name":"Binance BTC/USDT","dataProducts":[{"type":"Data Product","name":"Candles","id":"dd7c8795-bb24-4438-9d77-b37a9000ad7f","savedPayload":{"position":{"x":39655.39345377463,"y":28084.121285348076},"targetPosition":{"x":40780.996436099675,"y":27659.843516028},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Candles","id":"fe6065ec-4d2d-47a0-bae0-8647f0e195d7"}}},{"type":"Data Product","name":"Volumes","id":"98e6c917-f4b7-4b71-9215-de3ccaf3dc0c","savedPayload":{"position":{"x":39619.08803001109,"y":27971.34006849996},"targetPosition":{"x":40780.996436099675,"y":27659.843516028},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Volumes","id":"1a366aef-efef-470e-88e0-2a6fbe4dd91f"}}},{"type":"Data Product","name":"Candles Channels","id":"1d7dd537-5f6f-4eb2-8e56-ddba0aef720f","savedPayload":{"position":{"x":39594.11393185164,"y":27855.840877332517},"targetPosition":{"x":40780.996436099675,"y":27659.843516028},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Candles Channels","id":"8c81d378-0947-4e9d-be25-58e69120152e"}}},{"type":"Data Product","name":"Candles Channels Objects","id":"221c8d22-8a7f-4014-a7ed-0bafc886b123","savedPayload":{"position":{"x":39580.59887306321,"y":27738.507421368748},"targetPosition":{"x":40780.996436099675,"y":27659.843516028},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Candles Channels Objects","id":"ba5dbb67-2030-42a0-9ff8-1ee80874f047"}}},{"type":"Data Product","name":"Bollinger Bands","id":"6929ebe7-6486-4299-add5-ed0282500d91","savedPayload":{"position":{"x":39578.655464896365,"y":27620.63069875915},"targetPosition":{"x":40780.996436099675,"y":27659.843516028},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Bollinger Bands","id":"29088877-8d63-4217-8d34-8742afc262f4"}}},{"type":"Data Product","name":"Percentage Bandwidth","id":"4a3ed8eb-a73e-4fb4-835a-681cf47d7373","savedPayload":{"position":{"x":39588.297198778826,"y":27502.946480135615},"targetPosition":{"x":40780.996436099675,"y":27659.843516028},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Percentage Bandwidth","id":"3b7885a0-cd72-4a3f-a38b-3dc8c47bd068"}}},{"type":"Data Product","name":"Bollinger Channels Objects","id":"5ffc6a67-e33b-422b-8e36-f9711f93c723","savedPayload":{"position":{"x":39609.428887621216,"y":27386.77785099828},"targetPosition":{"x":40780.996436099675,"y":27659.843516028},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Bollinger Channels Objects","id":"1f111f72-624f-4166-9f99-ab8d785d5267"}}},{"type":"Data Product","name":"Bollinger Sub-Channels Objects","id":"48f7953c-f62d-4292-b042-d1ac05f8f80f","savedPayload":{"position":{"x":39641.84608404141,"y":27273.24280350331},"targetPosition":{"x":40780.996436099675,"y":27659.843516028},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Bollinger Sub-Channels Objects","id":"080c87fc-4546-4482-ab11-180a33f6d9ab"}}},{"type":"Data Product","name":"Popular SMAs","id":"3b9a3c93-6d41-440e-89a2-2fd1b2dde603","savedPayload":{"position":{"x":39685.2360649887,"y":27163.433854438405},"targetPosition":{"x":40780.996436099675,"y":27659.843516028},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapLine truncated
|
||||
@@ -1 +1 @@
|
||||
{"type":"Workspace","name":"Simple Workspace","rootNodes":[{"type":"Network","name":"Superalgos","networkNodes":[{"type":"Network Node","name":"My Computer","code":"{ \n\"host\": \"localhost\", \n\"webPort\": \"34247\", \n\"webSocketsPort\": \"8080\"\n}","dataStorage":{"type":"Data Storage","name":"New Data Storage","sessionIndependentData":{"type":"Session Independent Data","name":"New Session Independent Data","exchangeDataProducts":[{"type":"Exchange Data Products","name":"New Exchange Data Products","singleMarketData":[{"type":"Single Market Data","name":"","dataProducts":[{"type":"Data Product","name":"Candles","id":"cc7f62f2-0aa8-498c-861c-85060dd70522","savedPayload":{"position":{"x":39641.333811210454,"y":28936.98413868935},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Candles","id":"fe6065ec-4d2d-47a0-bae0-8647f0e195d7"}}},{"type":"Data Product","name":"Volumes","id":"70e3b1ab-65d9-4c9e-8489-35d6852e7ef5","savedPayload":{"position":{"x":39612.59634583407,"y":28848.5110343909},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Volumes","id":"1a366aef-efef-470e-88e0-2a6fbe4dd91f"}}},{"type":"Data Product","name":"Candles Channels","id":"eebb207f-6a7e-405a-9bed-2ff3afdd12af","savedPayload":{"position":{"x":39594.15352768551,"y":28758.904338266497},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Candles Channels","id":"8c81d378-0947-4e9d-be25-58e69120152e"}}},{"type":"Data Product","name":"Candles Channels Objects","id":"09706013-dc8f-4e40-8a71-129191aa521d","savedPayload":{"position":{"x":39585.513470979095,"y":28668.600155855387},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Candles Channels Objects","id":"ba5dbb67-2030-42a0-9ff8-1ee80874f047"}}},{"type":"Data Product","name":"Bollinger Bands","id":"d81b957c-4a39-4c15-8158-c05a0e63e591","savedPayload":{"position":{"x":39586.515890435076,"y":28578.275802249987},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Bollinger Bands","id":"29088877-8d63-4217-8d34-8742afc262f4"}}},{"type":"Data Product","name":"Percentage Bandwidth","id":"dd2bbd8b-0c18-4cc2-b176-ad3b177a98a7","savedPayload":{"position":{"x":39597.01323868843,"y":28488.759535006342},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Percentage Bandwidth","id":"3b7885a0-cd72-4a3f-a38b-3dc8c47bd068"}}},{"type":"Data Product","name":"Bollinger Channels Objects","id":"c2f6e67c-b1b1-47d3-9600-cf18be037620","savedPayload":{"position":{"x":39616.82107043368,"y":28400.936525998834},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Bollinger Channels Objects","id":"1f111f72-624f-4166-9f99-ab8d785d5267"}}},{"type":"Data Product","name":"Bollinger Sub-Channels Objects","id":"074c15c8-317c-4358-963f-4186f245bb25","savedPayload":{"position":{"x":39645.70528040039,"y":28315.720626172813},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Bollinger Sub-Channels Objects","id":"080c87fc-4546-4482-ab11-180a33f6d9ab"}}},{"type":"Data Product","name":"Popular SMAs","id":"c4a5297a-6f84-4337-8cd8-4ebde8fa1ae5","savedPayload":{"position":{"x":39683.34058679891,"y":28234.020419812852},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollaLine truncated
|
||||
{"type":"Workspace","name":"Simple Workspace","rootNodes":[{"type":"Network","name":"Superalgos","networkNodes":[{"type":"Network Node","name":"My Computer","code":"{ \n\"host\": \"localhost\", \n\"webPort\": \"34247\", \n\"webSocketsPort\": \"8080\"\n}","dataStorage":{"type":"Data Storage","name":"New Data Storage","sessionIndependentData":{"type":"Session Independent Data","name":"New Session Independent Data","exchangeDataProducts":[{"type":"Exchange Data Products","name":"Binance","singleMarketData":[{"type":"Single Market Data","name":"Binance BTC/USDT","dataProducts":[{"type":"Data Product","name":"Candles","id":"dd7c8795-bb24-4438-9d77-b37a9000ad7f","savedPayload":{"position":{"x":39655.39345377463,"y":28084.121285348076},"targetPosition":{"x":40780.996436099675,"y":27659.843516028},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Candles","id":"fe6065ec-4d2d-47a0-bae0-8647f0e195d7"}}},{"type":"Data Product","name":"Volumes","id":"98e6c917-f4b7-4b71-9215-de3ccaf3dc0c","savedPayload":{"position":{"x":39619.08803001109,"y":27971.34006849996},"targetPosition":{"x":40780.996436099675,"y":27659.843516028},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Volumes","id":"1a366aef-efef-470e-88e0-2a6fbe4dd91f"}}},{"type":"Data Product","name":"Candles Channels","id":"1d7dd537-5f6f-4eb2-8e56-ddba0aef720f","savedPayload":{"position":{"x":39594.11393185164,"y":27855.840877332517},"targetPosition":{"x":40780.996436099675,"y":27659.843516028},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Candles Channels","id":"8c81d378-0947-4e9d-be25-58e69120152e"}}},{"type":"Data Product","name":"Candles Channels Objects","id":"221c8d22-8a7f-4014-a7ed-0bafc886b123","savedPayload":{"position":{"x":39580.59887306321,"y":27738.507421368748},"targetPosition":{"x":40780.996436099675,"y":27659.843516028},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Candles Channels Objects","id":"ba5dbb67-2030-42a0-9ff8-1ee80874f047"}}},{"type":"Data Product","name":"Bollinger Bands","id":"6929ebe7-6486-4299-add5-ed0282500d91","savedPayload":{"position":{"x":39578.655464896365,"y":27620.63069875915},"targetPosition":{"x":40780.996436099675,"y":27659.843516028},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Bollinger Bands","id":"29088877-8d63-4217-8d34-8742afc262f4"}}},{"type":"Data Product","name":"Percentage Bandwidth","id":"4a3ed8eb-a73e-4fb4-835a-681cf47d7373","savedPayload":{"position":{"x":39588.297198778826,"y":27502.946480135615},"targetPosition":{"x":40780.996436099675,"y":27659.843516028},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Percentage Bandwidth","id":"3b7885a0-cd72-4a3f-a38b-3dc8c47bd068"}}},{"type":"Data Product","name":"Bollinger Channels Objects","id":"5ffc6a67-e33b-422b-8e36-f9711f93c723","savedPayload":{"position":{"x":39609.428887621216,"y":27386.77785099828},"targetPosition":{"x":40780.996436099675,"y":27659.843516028},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Bollinger Channels Objects","id":"1f111f72-624f-4166-9f99-ab8d785d5267"}}},{"type":"Data Product","name":"Bollinger Sub-Channels Objects","id":"48f7953c-f62d-4292-b042-d1ac05f8f80f","savedPayload":{"position":{"x":39641.84608404141,"y":27273.24280350331},"targetPosition":{"x":40780.996436099675,"y":27659.843516028},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Bollinger Sub-Channels Objects","id":"080c87fc-4546-4482-ab11-180a33f6d9ab"}}},{"type":"Data Product","name":"Popular SMAs","id":"3b9a3c93-6d41-440e-89a2-2fd1b2dde603","savedPayload":{"position":{"x":39685.2360649887,"y":27163.433854438405},"targetPosition":{"x":40780.996436099675,"y":27659.843516028},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed"Line truncated
|
||||
@@ -1 +1 @@
|
||||
{"type":"Super Scripts","name":"Masters","code":"{ \n\"codeName\": \"Masters\"\n}","scriptsLibrary":{"type":"Scripts Library","name":"New Scripts Library","masterScripts":[{"type":"Master Script","name":"Setup Market","templateScripts":[{"type":"Template Script","name":"Install Single Market Data","templateStructure":{"type":"Template Structure","name":"New Template Structure","singleMarketData":{"type":"Single Market Data","name":"","dataProducts":[{"type":"Data Product","name":"Candles","id":"24c5f795-acf3-43c3-99ee-ddb521b082f4","savedPayload":{"position":{"x":39641.333811210454,"y":28936.98413868935},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Candles","id":"fe6065ec-4d2d-47a0-bae0-8647f0e195d7"}}},{"type":"Data Product","name":"Volumes","id":"204ec959-0861-486a-aa2a-276dbf48f775","savedPayload":{"position":{"x":39612.59634583407,"y":28848.5110343909},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Volumes","id":"1a366aef-efef-470e-88e0-2a6fbe4dd91f"}}},{"type":"Data Product","name":"Candles Channels","id":"90ee9733-ab7e-41a0-ac78-4a7661a27017","savedPayload":{"position":{"x":39594.15352768551,"y":28758.904338266497},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Candles Channels","id":"8c81d378-0947-4e9d-be25-58e69120152e"}}},{"type":"Data Product","name":"Candles Channels Objects","id":"9ade8e93-9071-422b-8cce-7a50d6dad739","savedPayload":{"position":{"x":39585.513470979095,"y":28668.600155855387},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Candles Channels Objects","id":"ba5dbb67-2030-42a0-9ff8-1ee80874f047"}}},{"type":"Data Product","name":"Bollinger Bands","id":"b5ef2cf7-3d35-45ec-848c-31970b59c04e","savedPayload":{"position":{"x":39586.515890435076,"y":28578.275802249987},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Bollinger Bands","id":"29088877-8d63-4217-8d34-8742afc262f4"}}},{"type":"Data Product","name":"Percentage Bandwidth","id":"1c3881ca-24b3-4cc9-b16b-9db7aa2b4c24","savedPayload":{"position":{"x":39597.01323868843,"y":28488.759535006342},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Percentage Bandwidth","id":"3b7885a0-cd72-4a3f-a38b-3dc8c47bd068"}}},{"type":"Data Product","name":"Bollinger Channels Objects","id":"92eec33b-86be-4b73-899f-e9550f7b0df3","savedPayload":{"position":{"x":39616.82107043368,"y":28400.936525998834},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Bollinger Channels Objects","id":"1f111f72-624f-4166-9f99-ab8d785d5267"}}},{"type":"Data Product","name":"Bollinger Sub-Channels Objects","id":"4b69df71-9091-4d22-9b0d-571304297033","savedPayload":{"position":{"x":39645.70528040039,"y":28315.720626172813},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Bollinger Sub-Channels Objects","id":"080c87fc-4546-4482-ab11-180a33f6d9ab"}}},{"type":"Data Product","name":"Popular SMAs","id":"8a5f7e27-9ca5-4d6e-b6b9-2d6cbdda8040","savedPayload":{"position":{"x":39683.34058679891,"y":28234.020419812852},"targetPosition":{"x":40443.285556188,"y":28633.794640045882},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":Line truncated
|
||||
{"type":"Super Scripts","name":"Masters","code":"{ \n\"codeName\": \"Masters\"\n}","scriptsLibrary":{"type":"Scripts Library","name":"New Scripts Library","masterScripts":[{"type":"Master Script","name":"Setup Market","templateScripts":[{"type":"Template Script","name":"Install Single Market Data","templateStructure":{"type":"Template Structure","name":"New Template Structure","singleMarketData":{"type":"Single Market Data","name":"","dataProducts":[{"type":"Data Product","name":"Candles","id":"24c5f795-acf3-43c3-99ee-ddb521b082f4","savedPayload":{"position":{"x":39655.39345377463,"y":28084.121285348076},"targetPosition":{"x":40780.996436099675,"y":27659.843516028},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Candles","id":"fe6065ec-4d2d-47a0-bae0-8647f0e195d7"}}},{"type":"Data Product","name":"Volumes","id":"204ec959-0861-486a-aa2a-276dbf48f775","savedPayload":{"position":{"x":39619.08803001109,"y":27971.34006849996},"targetPosition":{"x":40780.996436099675,"y":27659.843516028},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Volumes","id":"1a366aef-efef-470e-88e0-2a6fbe4dd91f"}}},{"type":"Data Product","name":"Candles Channels","id":"90ee9733-ab7e-41a0-ac78-4a7661a27017","savedPayload":{"position":{"x":39594.11393185164,"y":27855.840877332517},"targetPosition":{"x":40780.996436099675,"y":27659.843516028},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Candles Channels","id":"8c81d378-0947-4e9d-be25-58e69120152e"}}},{"type":"Data Product","name":"Candles Channels Objects","id":"9ade8e93-9071-422b-8cce-7a50d6dad739","savedPayload":{"position":{"x":39580.59887306321,"y":27738.507421368748},"targetPosition":{"x":40780.996436099675,"y":27659.843516028},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Candles Channels Objects","id":"ba5dbb67-2030-42a0-9ff8-1ee80874f047"}}},{"type":"Data Product","name":"Bollinger Bands","id":"b5ef2cf7-3d35-45ec-848c-31970b59c04e","savedPayload":{"position":{"x":39578.655464896365,"y":27620.63069875915},"targetPosition":{"x":40780.996436099675,"y":27659.843516028},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Bollinger Bands","id":"29088877-8d63-4217-8d34-8742afc262f4"}}},{"type":"Data Product","name":"Percentage Bandwidth","id":"1c3881ca-24b3-4cc9-b16b-9db7aa2b4c24","savedPayload":{"position":{"x":39588.297198778826,"y":27502.946480135615},"targetPosition":{"x":40780.996436099675,"y":27659.843516028},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Percentage Bandwidth","id":"3b7885a0-cd72-4a3f-a38b-3dc8c47bd068"}}},{"type":"Data Product","name":"Bollinger Channels Objects","id":"92eec33b-86be-4b73-899f-e9550f7b0df3","savedPayload":{"position":{"x":39609.428887621216,"y":27386.77785099828},"targetPosition":{"x":40780.996436099675,"y":27659.843516028},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Bollinger Channels Objects","id":"1f111f72-624f-4166-9f99-ab8d785d5267"}}},{"type":"Data Product","name":"Bollinger Sub-Channels Objects","id":"4b69df71-9091-4d22-9b0d-571304297033","savedPayload":{"position":{"x":39641.84608404141,"y":27273.24280350331},"targetPosition":{"x":40780.996436099675,"y":27659.843516028},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":true,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"Product Definition","name":"Bollinger Sub-Channels Objects","id":"080c87fc-4546-4482-ab11-180a33f6d9ab"}}},{"type":"Data Product","name":"Popular SMAs","id":"8a5f7e27-9ca5-4d6e-b6b9-2d6cbdda8040","savedPayload":{"position":{"x":39685.2360649887,"y":27163.433854438405},"targetPosition":{"x":40780.996436099675,"y":27659.843516028},"floatingObject":{"isPinned":false,"isFrozen":false,"isCollapsed":false,"angleToParent":2,"distanceToParent":3,"arrangementStyle":0},"uiObject":{"isRunning":false},"referenceParent":{"type":"PLine truncated
|
||||
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Launch Program",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"program": "${workspaceFolder}\\server.js"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
const FULL_LOG = true;
|
||||
const LOG_FILE_CONTENT = false;
|
||||
const ONE_DAY_IN_MILISECONDS = 24 * 60 * 60 * 1000;
|
||||
const ONE_MIN_IN_MILISECONDS = 60 * 1000;
|
||||
|
||||
const MODULE_NAME = "Commons";
|
||||
|
||||
@@ -55,6 +56,11 @@
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
return
|
||||
}
|
||||
if (outputDatasetNode.referenceParent.parentNode === undefined) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> Dataset not a child of a Product Definition. Dataset = " + JSON.stringify(outputDatasetNode.referenceParent));
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
return
|
||||
}
|
||||
if (outputDatasetNode.referenceParent.parentNode.code.singularVariableName === undefined) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> Product Definition without a Single Variable Name defined. Product Definition = " + JSON.stringify(outputDatasetNode.referenceParent.parentNode));
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
@@ -284,7 +290,8 @@
|
||||
let yesterday = {}
|
||||
let system = { // These are the available system variables to be used in User Code and Formulas
|
||||
timeFrame: timeFrame,
|
||||
ONE_DAY_IN_MILISECONDS: ONE_DAY_IN_MILISECONDS
|
||||
ONE_DAY_IN_MILISECONDS: ONE_DAY_IN_MILISECONDS,
|
||||
ONE_MIN_IN_MILISECONDS: ONE_MIN_IN_MILISECONDS
|
||||
}
|
||||
let variable = {} // This is the structure where the user will define its own variables that will be shared across different code blocks and formulas.
|
||||
let results = []
|
||||
|
||||
+23
-23
@@ -5,7 +5,7 @@
|
||||
const ONE_YEAR_IN_MILISECONDS = 365 * 24 * 60 * 60 * 1000
|
||||
|
||||
let thisObject = {
|
||||
initialize: initialize
|
||||
initialize: initialize
|
||||
}
|
||||
|
||||
return thisObject;
|
||||
@@ -17,10 +17,10 @@
|
||||
let telegramAPI
|
||||
|
||||
/* Initialize this info so that everything is logged propeerly */
|
||||
|
||||
|
||||
bot.SESSION = {
|
||||
name: bot.processNode.session.name,
|
||||
id: bot.processNode.session.id
|
||||
id: bot.processNode.session.id
|
||||
}
|
||||
|
||||
/* Set the folderName for early logging */
|
||||
@@ -29,7 +29,7 @@
|
||||
} else {
|
||||
bot.SESSION.folderName = bot.processNode.session.code.folderName + "-" + bot.SESSION.id
|
||||
}
|
||||
|
||||
|
||||
/* Check if there is a session */
|
||||
if (bot.processNode.session === undefined) {
|
||||
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> Cannot run without a Session.");
|
||||
@@ -40,7 +40,7 @@
|
||||
/* Listen to event to start or stop the session. */
|
||||
bot.sessionKey = bot.processNode.session.name + '-' + bot.processNode.session.type + '-' + bot.processNode.session.id
|
||||
global.SESSION_MAP.set(bot.sessionKey, bot.sessionKey)
|
||||
|
||||
|
||||
global.EVENT_SERVER_CLIENT.listenToEvent(bot.sessionKey, 'Run Session', undefined, bot.sessionKey, undefined, runSession)
|
||||
global.EVENT_SERVER_CLIENT.listenToEvent(bot.sessionKey, 'Stop Session', undefined, bot.sessionKey, undefined, stopSession)
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
}
|
||||
bot.resumeExecution = false;
|
||||
bot.hasTheBotJustStarted = true
|
||||
bot.multiPeriodProcessDatetime = new Date(bot.VALUES_TO_USE.timeRange.initialDatetime.valueOf())
|
||||
bot.multiPeriodProcessDatetime = new Date(bot.VALUES_TO_USE.timeRange.initialDatetime.valueOf())
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@
|
||||
bot.startMode = "Live"
|
||||
checkDatetimes()
|
||||
bot.resumeExecution = false;
|
||||
bot.multiPeriodProcessDatetime = new Date(bot.VALUES_TO_USE.timeRange.initialDatetime.valueOf())
|
||||
bot.multiPeriodProcessDatetime = new Date(bot.VALUES_TO_USE.timeRange.initialDatetime.valueOf())
|
||||
bot.hasTheBotJustStarted = true
|
||||
pProcessConfig.liveWaitTime = getTimeFrameFromLabel(bot.VALUES_TO_USE.timeFrame)
|
||||
return true
|
||||
@@ -165,23 +165,23 @@
|
||||
bot.startMode = "Live"
|
||||
checkDatetimes()
|
||||
bot.resumeExecution = false;
|
||||
bot.multiPeriodProcessDatetime = new Date(bot.VALUES_TO_USE.timeRange.initialDatetime.valueOf())
|
||||
bot.multiPeriodProcessDatetime = new Date(bot.VALUES_TO_USE.timeRange.initialDatetime.valueOf())
|
||||
bot.hasTheBotJustStarted = true
|
||||
|
||||
/* Reduce the balance */
|
||||
|
||||
let balancePercentage = 1 // This is the default value
|
||||
|
||||
|
||||
if (bot.SESSION.code.balancePercentage !== undefined) {
|
||||
balancePercentage = bot.SESSION.code.balancePercentage
|
||||
}
|
||||
|
||||
bot.VALUES_TO_USE.initialBalanceA = bot.VALUES_TO_USE.initialBalanceA * balancePercentage / 100
|
||||
bot.VALUES_TO_USE.initialBalanceB = bot.VALUES_TO_USE.initialBalanceB * balancePercentage / 100
|
||||
|
||||
|
||||
bot.VALUES_TO_USE.minimumBalanceA = bot.VALUES_TO_USE.minimumBalanceA * balancePercentage / 100
|
||||
bot.VALUES_TO_USE.minimumBalanceB = bot.VALUES_TO_USE.minimumBalanceB * balancePercentage / 100
|
||||
|
||||
|
||||
bot.VALUES_TO_USE.maximumBalanceA = bot.VALUES_TO_USE.maximumBalanceA * balancePercentage / 100
|
||||
bot.VALUES_TO_USE.maximumBalanceB = bot.VALUES_TO_USE.maximumBalanceB * balancePercentage / 100
|
||||
|
||||
@@ -191,12 +191,12 @@
|
||||
}
|
||||
|
||||
function startPaperTrading(message) {
|
||||
bot.startMode = "Backtest"
|
||||
|
||||
bot.startMode = "Paper"
|
||||
|
||||
checkDatetimes()
|
||||
bot.resumeExecution = false;
|
||||
bot.hasTheBotJustStarted = true
|
||||
bot.multiPeriodProcessDatetime = new Date(bot.VALUES_TO_USE.timeRange.initialDatetime.valueOf())
|
||||
bot.multiPeriodProcessDatetime = new Date(bot.VALUES_TO_USE.timeRange.initialDatetime.valueOf())
|
||||
pProcessConfig.normalWaitTime = getTimeFrameFromLabel(bot.VALUES_TO_USE.timeFrame)
|
||||
return true
|
||||
}
|
||||
@@ -270,7 +270,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
let tradingSystem = bot.TRADING_SYSTEM
|
||||
let tradingSystem = bot.TRADING_SYSTEM
|
||||
|
||||
if (tradingSystem !== undefined) {
|
||||
|
||||
@@ -429,7 +429,7 @@
|
||||
let socialBot = bot.SESSION.socialBots.bots[i]
|
||||
if (socialBot.type === "Telegram Bot") {
|
||||
let code = socialBot.code
|
||||
socialBot.botInstance = initializeTelegramBot(code.botToken, code.chatId)
|
||||
socialBot.botInstance = initializeTelegramBot(code.botToken, code.chatId)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -440,7 +440,7 @@
|
||||
let socialBot = bot.SESSION.socialBots.bots[i]
|
||||
try {
|
||||
let code = announcement.code
|
||||
|
||||
|
||||
if (socialBot.type === "Telegram Bot") {
|
||||
if (announcement.formulaValue !== undefined) {
|
||||
socialBot.botInstance.telegramAPI.sendMessage(socialBot.botInstance.chatId, announcement.formulaValue).catch(err => parentLogger.write(MODULE_NAME, "[WARN] initialize -> initializeSocialBots -> announce -> Telegram API error -> err = " + err))
|
||||
@@ -448,7 +448,7 @@
|
||||
socialBot.botInstance.telegramAPI.sendMessage(socialBot.botInstance.chatId, code.text).catch(err => parentLogger.write(MODULE_NAME, "[WARN] initialize -> initializeSocialBots -> announce -> Telegram API error -> err = " + err))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} catch (err) {
|
||||
parentLogger.write(MODULE_NAME, "[WARN] initialize -> initializeSocialBots -> announce -> err = " + err.stack);
|
||||
}
|
||||
@@ -461,7 +461,7 @@
|
||||
}
|
||||
|
||||
function finalizeSocialBots() {
|
||||
if (bot.SESSION.socialBots === undefined) {return}
|
||||
if (bot.SESSION.socialBots === undefined) { return }
|
||||
if (bot.SESSION.socialBots.bots !== undefined) {
|
||||
for (let i = 0; i < bot.SESSION.socialBots.bots.length; i++) {
|
||||
let socialBot = bot.SESSION.socialBots.bots[i]
|
||||
@@ -488,8 +488,8 @@
|
||||
|
||||
telegramAPI = new Telegram(botToken)
|
||||
|
||||
const messge = bot.SESSION.type + " '" + bot.SESSION.name + "' was started with an initial balance of " + " " + bot.VALUES_TO_USE.initialBalanceA + " " + bot.VALUES_TO_USE.baseAsset + "."
|
||||
telegramAPI.sendMessage(chatId, messge ).catch(err => parentLogger.write(MODULE_NAME, "[WARN] initialize -> initializeTelegramBot -> Telegram API error -> err = " + err))
|
||||
const messge = bot.SESSION.type + " '" + bot.SESSION.name + "' was started with an initial balance of " + " " + bot.VALUES_TO_USE.initialBalanceA + " " + bot.VALUES_TO_USE.baseAsset + "."
|
||||
telegramAPI.sendMessage(chatId, messge).catch(err => parentLogger.write(MODULE_NAME, "[WARN] initialize -> initializeTelegramBot -> Telegram API error -> err = " + err))
|
||||
|
||||
let botInstance = {
|
||||
telegramBot: telegramBot,
|
||||
@@ -504,10 +504,10 @@
|
||||
}
|
||||
|
||||
function finalizeTelegramBot(chatId) {
|
||||
const messge = bot.SESSION.type + " '" + bot.SESSION.name + "' was stopped."
|
||||
const messge = bot.SESSION.type + " '" + bot.SESSION.name + "' was stopped."
|
||||
telegramAPI.sendMessage(chatId, messge).catch(err => parentLogger.write(MODULE_NAME, "[WARN] initialize -> initializeTelegramBot -> Telegram API error -> err = " + err))
|
||||
}
|
||||
|
||||
|
||||
} catch (err) {
|
||||
parentLogger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
|
||||
+147
-87
@@ -121,6 +121,7 @@
|
||||
const CONDITIONS_FOLDER_NAME = "Simulation-Conditions";
|
||||
const STRATEGIES_FOLDER_NAME = "Simulation-Strategies";
|
||||
const TRADES_FOLDER_NAME = "Simulation-Trades";
|
||||
const SNAPSHOTS_FOLDER_NAME = "Snapshots";
|
||||
|
||||
const ONE_DAY_IN_MILISECONDS = 24 * 60 * 60 * 1000;
|
||||
|
||||
@@ -129,6 +130,10 @@
|
||||
let strategiesArray
|
||||
let tradesArray
|
||||
|
||||
let snapshotHeaders
|
||||
let triggerOnSnapshot
|
||||
let takePositionSnapshot
|
||||
|
||||
let tradingSystem = {};
|
||||
|
||||
tradingSimulation.runSimulation(
|
||||
@@ -142,7 +147,7 @@
|
||||
writeFiles,
|
||||
callBackFunction)
|
||||
|
||||
function writeFiles(pTradingSystem, pRecordsArray, pConditionsArray, pStrategiesArray, pTradesArray) {
|
||||
function writeFiles(pTradingSystem, pRecordsArray, pConditionsArray, pStrategiesArray, pTradesArray, pSnapshotHeaders, pTriggerOnSnapshot, pTakePositionSnapshot) {
|
||||
|
||||
tradingSystem = pTradingSystem
|
||||
recordsArray = pRecordsArray
|
||||
@@ -150,11 +155,16 @@
|
||||
strategiesArray = pStrategiesArray
|
||||
tradesArray = pTradesArray
|
||||
|
||||
snapshotHeaders = pSnapshotHeaders
|
||||
triggerOnSnapshot = pTriggerOnSnapshot
|
||||
takePositionSnapshot = pTakePositionSnapshot
|
||||
|
||||
if (timeFrame > global.dailyFilePeriods[0][0]) {
|
||||
writeMarketFiles()
|
||||
} else {
|
||||
writeDailyFiles()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function writeMarketFiles() {
|
||||
@@ -367,7 +377,8 @@
|
||||
record.number + "," +
|
||||
record.beginRate + "," +
|
||||
record.endRate + "," +
|
||||
'"' + record.triggerOnSituation + '"' + "]";
|
||||
'"' + record.triggerOnSituation + '"' + "," +
|
||||
'"' + record.name + '"' + "]";
|
||||
|
||||
if (separator === "") { separator = ","; }
|
||||
|
||||
@@ -474,7 +485,7 @@
|
||||
|
||||
}
|
||||
|
||||
callBackFunction(global.DEFAULT_OK_RESPONSE);
|
||||
writeSnapshotFiles();
|
||||
|
||||
}
|
||||
catch (err) {
|
||||
@@ -489,97 +500,52 @@
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
function writeSnapshotFiles() {
|
||||
|
||||
function writeDailyFiles() {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDailyFiles -> Entering function."); }
|
||||
writeSnapshotFile(triggerOnSnapshot, 'Trigger-On', onFinish)
|
||||
|
||||
writeRecordsFile();
|
||||
function onFinish() {
|
||||
writeSnapshotFile(takePositionSnapshot, 'Take-Position', callBackFunction)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* TODO : NEXT function is a work in progress, not used today */
|
||||
function writeFinalResults() {
|
||||
function writeSnapshotFile(snapshotArray, pFileName, callBack) {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDailyFiles -> writeFinalResults -> Entering function."); }
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeMarketFiles -> writeSnapshotFile -> Entering function."); }
|
||||
|
||||
if ( // We only write this file if we are at the head of the market.
|
||||
Math.trunc(currentDay.valueOf() / ONE_DAY_IN_MILISECONDS) * ONE_DAY_IN_MILISECONDS
|
||||
!==
|
||||
Math.trunc((new Date()).valueOf() / ONE_DAY_IN_MILISECONDS) * ONE_DAY_IN_MILISECONDS
|
||||
) {
|
||||
writeRecordsFile();
|
||||
return;
|
||||
}
|
||||
|
||||
let separator = "";
|
||||
let fileRecordCounter = 0;
|
||||
|
||||
let fileContent = "";
|
||||
let separator = "\r\n";
|
||||
|
||||
for (let i = 0; i < recordsArray.length; i++) {
|
||||
|
||||
let record = recordsArray[i];
|
||||
|
||||
/* Will only add to the file the records of the current day */
|
||||
|
||||
if (record.begin < currentDay.valueOf()) { continue; }
|
||||
|
||||
fileContent = fileContent + separator + '[' +
|
||||
record.begin + "," +
|
||||
record.end + "," +
|
||||
record.type + "," +
|
||||
record.marketRate + "," +
|
||||
record.amount + "," +
|
||||
record.balanceA + "," +
|
||||
record.balanceB + "," +
|
||||
record.profit + "," +
|
||||
record.lastTradeProfitLoss + "," +
|
||||
record.stopLoss + "," +
|
||||
record.roundtrips + "," +
|
||||
record.hits + "," +
|
||||
record.fails + "," +
|
||||
record.hitRatio + "," +
|
||||
record.ROI + "," +
|
||||
record.periods + "," +
|
||||
record.days + "," +
|
||||
record.anualizedRateOfReturn + "," +
|
||||
record.positionRate + "," +
|
||||
record.lastTradeROI + "," +
|
||||
record.strategy + "," +
|
||||
record.strategyStageNumber + "," +
|
||||
record.takeProfit + "," +
|
||||
record.stopLossPhase + "," +
|
||||
record.takeProfitPhase + "," +
|
||||
JSON.stringify(record.executionRecord) + "," +
|
||||
record.positionSize + "," +
|
||||
record.initialBalanceA + "," +
|
||||
record.minimumBalanceA + "," +
|
||||
record.maximumBalanceA + "," +
|
||||
record.initialBalanceB + "," +
|
||||
record.minimumBalanceB + "," +
|
||||
record.maximumBalanceB + "," +
|
||||
record.baseAsset + "," +
|
||||
record.quotedAsset + "," +
|
||||
record.marketBaseAsset + "," +
|
||||
record.marketQuotedAsset + "," +
|
||||
record.positionPeriods + "," +
|
||||
record.positionDays + "," +
|
||||
record.distanceToLastTriggerOn + "," +
|
||||
record.distanceToLastTriggerOff + "," +
|
||||
record.distanceToLastTakePosition + "," +
|
||||
record.distanceToLastClosePosition + "]";
|
||||
|
||||
if (separator === "") { separator = ","; }
|
||||
parseRecord(snapshotHeaders)
|
||||
|
||||
for (let i = 0; i < snapshotArray.length; i++) {
|
||||
let record = snapshotArray[i];
|
||||
parseRecord(record)
|
||||
fileRecordCounter++;
|
||||
}
|
||||
|
||||
function parseRecord(record) {
|
||||
for (let j = 0; j < record.length; j++) {
|
||||
let property = record[j]
|
||||
|
||||
fileContent = fileContent + '' + property
|
||||
if (j !== record.length - 1) {
|
||||
fileContent = fileContent + ","
|
||||
}
|
||||
}
|
||||
fileContent = fileContent + separator
|
||||
|
||||
}
|
||||
|
||||
fileContent = "[" + fileContent + "]";
|
||||
fileContent = "" + fileContent + "";
|
||||
|
||||
let fileName = 'Data.json';
|
||||
let filePath = bot.filePathRoot + "/Output/" + bot.SESSION.folderName + "/" + SIMULATED_RECORDS_FOLDER_NAME + "/" + "Multi-Period-Daily" + "/" + timeFrameLabel;
|
||||
let fileName = pFileName + '.csv';
|
||||
let filePath = bot.filePathRoot + "/Output/" + bot.SESSION.folderName + "/" + SNAPSHOTS_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timeFrameLabel;
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.createTextFile(filePath, fileContent + '\n', onFileCreated);
|
||||
@@ -588,35 +554,42 @@
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDailyFiles -> writeFinalResults -> onFileCreated -> Entering function."); }
|
||||
if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDailyFiles -> writeFinalResults -> onFileCreated -> fileContent = " + fileContent); }
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeMarketFiles -> writeSnapshotFile -> onFileCreated -> Entering function."); }
|
||||
if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> writeMarketFiles -> writeSnapshotFile -> onFileCreated -> fileContent = " + fileContent); }
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeFinalResults -> onFileCreated -> err = " + err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeFinalResults -> onFileCreated -> filePath = " + filePath);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeFinalResults -> onFileCreated -> market = " + market.baseAsset + "_" + market.quotedAsset);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeMarketFiles -> writeSnapshotFile -> onFileCreated -> err = " + err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeMarketFiles -> writeSnapshotFile -> onFileCreated -> filePath = " + filePath);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeMarketFiles -> writeSnapshotFile -> onFileCreated -> market = " + market.baseAsset + "_" + market.quotedAsset);
|
||||
|
||||
callBackFunction(err);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
writeRecordsFile();
|
||||
callBack(global.DEFAULT_OK_RESPONSE);
|
||||
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeFinalResults -> onFileCreated -> err = " + err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeMarketFiles -> writeSnapshotFile -> onFileCreated -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeFinalResults -> err = " + err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeMarketFiles -> writeSnapshotFile -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function writeDailyFiles() {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDailyFiles -> Entering function."); }
|
||||
|
||||
writeRecordsFile();
|
||||
|
||||
function writeRecordsFile() {
|
||||
|
||||
try {
|
||||
@@ -841,7 +814,8 @@
|
||||
record.number + "," +
|
||||
record.beginRate + "," +
|
||||
record.endRate + "," +
|
||||
'"' + record.triggerOnSituation + '"' + "]";
|
||||
'"' + record.triggerOnSituation + '"' + "," +
|
||||
'"' + record.name + '"' + "]";
|
||||
|
||||
if (separator === "") { separator = ","; }
|
||||
|
||||
@@ -955,7 +929,7 @@
|
||||
|
||||
}
|
||||
|
||||
callBackFunction(global.DEFAULT_OK_RESPONSE);
|
||||
writeSnapshotFiles()
|
||||
|
||||
}
|
||||
catch (err) {
|
||||
@@ -970,6 +944,92 @@
|
||||
}
|
||||
}
|
||||
|
||||
function writeSnapshotFiles() {
|
||||
|
||||
writeSnapshotFile(triggerOnSnapshot, 'Trigger-On', onFinish)
|
||||
|
||||
function onFinish() {
|
||||
writeSnapshotFile(takePositionSnapshot, 'Take-Position', callBackFunction)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function writeSnapshotFile(snapshotArray, pFileName, callBack) {
|
||||
if (bot.startMode !== 'Backtest') {
|
||||
callBack(global.DEFAULT_OK_RESPONSE);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDailyFiles -> writeSnapshotFile -> Entering function."); }
|
||||
|
||||
let fileRecordCounter = 0;
|
||||
|
||||
let fileContent = "";
|
||||
let separator = "\r\n";
|
||||
|
||||
parseRecord(snapshotHeaders)
|
||||
|
||||
for (let i = 0; i < snapshotArray.length; i++) {
|
||||
let record = snapshotArray[i];
|
||||
parseRecord(record)
|
||||
fileRecordCounter++;
|
||||
}
|
||||
|
||||
function parseRecord(record) {
|
||||
for (let j = 0; j < record.length; j++) {
|
||||
let property = record[j]
|
||||
|
||||
fileContent = fileContent + '' + property
|
||||
if (j !== record.length - 1) {
|
||||
fileContent = fileContent + ","
|
||||
}
|
||||
}
|
||||
fileContent = fileContent + separator
|
||||
|
||||
}
|
||||
|
||||
fileContent = "" + fileContent + "";
|
||||
|
||||
let dateForPath = currentDay.getUTCFullYear() + '/' + utilities.pad(currentDay.getUTCMonth() + 1, 2) + '/' + utilities.pad(currentDay.getUTCDate(), 2);
|
||||
let fileName = pFileName + '.csv';
|
||||
let filePath = bot.filePathRoot + "/Output/" + bot.SESSION.folderName + "/" + SNAPSHOTS_FOLDER_NAME + "/" + "Multi-Period-Daily" + "/" + timeFrameLabel + "/" + dateForPath;
|
||||
filePath += '/' + fileName
|
||||
|
||||
fileStorage.createTextFile(filePath, fileContent + '\n', onFileCreated);
|
||||
|
||||
function onFileCreated(err) {
|
||||
|
||||
try {
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDailyFiles -> writeSnapshotFile -> onFileCreated -> Entering function."); }
|
||||
if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDailyFiles -> writeSnapshotFile -> onFileCreated -> fileContent = " + fileContent); }
|
||||
|
||||
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
|
||||
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeSnapshotFile -> onFileCreated -> err = " + err.stack);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeSnapshotFile -> onFileCreated -> filePath = " + filePath);
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeSnapshotFile -> onFileCreated -> market = " + market.baseAsset + "_" + market.quotedAsset);
|
||||
|
||||
callBackFunction(err);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
callBack(global.DEFAULT_OK_RESPONSE);
|
||||
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeSnapshotFile -> onFileCreated -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeSnapshotFile -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
|
||||
+251
-29
@@ -56,13 +56,13 @@
|
||||
|
||||
/* Stop Loss Management */
|
||||
|
||||
const MIN_STOP_LOSS_VALUE = 1 // We can not let the stop be zero to avoid division by 0 error or infinity numbers as a result.
|
||||
const MIN_STOP_LOSS_VALUE = 0.0000000001 // We can not let the stop be zero to avoid division by 0 error or infinity numbers as a result.
|
||||
const MAX_STOP_LOSS_VALUE = Number.MAX_SAFE_INTEGER
|
||||
let stopLoss = 0;
|
||||
|
||||
/* Take Profit Management */
|
||||
|
||||
const MIN_TAKE_PROFIT_VALUE = 1 // We can not let the buy order be zero to avoid division by 0 error or infinity numbers as a result.
|
||||
const MIN_TAKE_PROFIT_VALUE = 0.0000000001 // We can not let the buy order be zero to avoid division by 0 error or infinity numbers as a result.
|
||||
const MAX_TAKE_PROFIT_VALUE = Number.MAX_SAFE_INTEGER
|
||||
let takeProfit = 0;
|
||||
|
||||
@@ -103,6 +103,15 @@
|
||||
interExecutionMemory.
|
||||
*/
|
||||
|
||||
/* Snapshots of Trigger On and Take Positions */
|
||||
let snapshots = {
|
||||
headers: undefined,
|
||||
triggerOn: [],
|
||||
takePosition: [],
|
||||
lastTriggerOn: undefined,
|
||||
lastTakePosition: undefined
|
||||
}
|
||||
|
||||
/*Needed for statistics */
|
||||
let previousBalanceBaseAsset = 0;
|
||||
let previousBalanceQuotedAsset = 0;
|
||||
@@ -130,7 +139,8 @@
|
||||
number: 0,
|
||||
beginRate: 0,
|
||||
endRate: 0,
|
||||
triggerOnSituation: ''
|
||||
triggerOnSituation: '',
|
||||
name: ''
|
||||
}
|
||||
|
||||
let currentTrade = {
|
||||
@@ -181,6 +191,15 @@
|
||||
|
||||
/* Initialization */
|
||||
|
||||
|
||||
yesterday.snapshots = {
|
||||
headers: undefined,
|
||||
triggerOn: [],
|
||||
takePosition: [],
|
||||
lastTriggerOn: undefined,
|
||||
lastTakePosition: undefined
|
||||
}
|
||||
|
||||
yesterday.stopLoss = 0
|
||||
yesterday.takeProfit = 0
|
||||
|
||||
@@ -206,7 +225,8 @@
|
||||
number: 0,
|
||||
beginRate: 0,
|
||||
endRate: 0,
|
||||
triggerOnSituation: ''
|
||||
triggerOnSituation: '',
|
||||
name: ''
|
||||
}
|
||||
|
||||
yesterday.currentTrade = {
|
||||
@@ -251,6 +271,14 @@
|
||||
|
||||
/* Initialize the data structure we will use inter execution. */
|
||||
|
||||
interExecutionMemory.snapshots = {
|
||||
headers: undefined,
|
||||
triggerOn: [],
|
||||
takePosition: [],
|
||||
lastTriggerOn: undefined,
|
||||
lastTakePosition: undefined
|
||||
}
|
||||
|
||||
interExecutionMemory.stopLoss = 0
|
||||
interExecutionMemory.takeProfit = 0
|
||||
|
||||
@@ -276,7 +304,8 @@
|
||||
number: 0,
|
||||
beginRate: 0,
|
||||
endRate: 0,
|
||||
triggerOnSituation: ''
|
||||
triggerOnSituation: '',
|
||||
name: ''
|
||||
}
|
||||
|
||||
interExecutionMemory.currentTrade = {
|
||||
@@ -323,6 +352,14 @@
|
||||
|
||||
/* We get the initial values from the day previous to the candles we receive at the current execution */
|
||||
|
||||
snapshots = {
|
||||
headers: interExecutionMemory.snapshots.headers,
|
||||
triggerOn: interExecutionMemory.snapshots.triggerOn,
|
||||
takePosition: interExecutionMemory.snapshots.takePosition,
|
||||
lastTriggerOn: interExecutionMemory.snapshots.lastTriggerOn,
|
||||
lastTakePosition: interExecutionMemory.snapshots.lastTakePosition
|
||||
}
|
||||
|
||||
stopLoss = interExecutionMemory.stopLoss
|
||||
takeProfit = interExecutionMemory.takeProfit
|
||||
|
||||
@@ -348,7 +385,8 @@
|
||||
number: interExecutionMemory.currentStrategy.number,
|
||||
beginRate: interExecutionMemory.currentStrategy.beginRate,
|
||||
endRate: interExecutionMemory.currentStrategy.endRate,
|
||||
triggerOnSituation: interExecutionMemory.currentStrategy.triggerOnSituation
|
||||
triggerOnSituation: interExecutionMemory.currentStrategy.triggerOnSituation,
|
||||
name: currentStrategy.name
|
||||
}
|
||||
|
||||
currentTrade = {
|
||||
@@ -398,6 +436,14 @@
|
||||
|
||||
/* For the case that any of these variables are not updated during the main loop, we need to store their value at the yesterday structure, otherwise it would be lost. */
|
||||
|
||||
yesterday.snapshots = {
|
||||
headers: snapshots.headers,
|
||||
triggerOn: snapshots.triggerOn,
|
||||
takePosition: snapshots.takePosition,
|
||||
lastTriggerOn: snapshots.lastTriggerOn,
|
||||
lastTakePosition: snapshots.lastTakePosition
|
||||
}
|
||||
|
||||
yesterday.stopLoss = stopLoss
|
||||
yesterday.takeProfit = takeProfit
|
||||
|
||||
@@ -423,7 +469,8 @@
|
||||
number: currentStrategy.number,
|
||||
beginRate: currentStrategy.beginRate,
|
||||
endRate: currentStrategy.endRate,
|
||||
triggerOnSituation: currentStrategy.triggerOnSituation
|
||||
triggerOnSituation: currentStrategy.triggerOnSituation,
|
||||
name: currentStrategy.name
|
||||
}
|
||||
|
||||
yesterday.currentTrade = {
|
||||
@@ -500,6 +547,15 @@
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> Entering function."); }
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> Processing candle # " + currentCandleIndex); }
|
||||
|
||||
/* We are going to take snapshots of the values of indicators at key moments of the sumulation. */
|
||||
|
||||
let snapshotKeys = new Map()
|
||||
snapshotLoopHeaders = []
|
||||
snapshotDataRecord = []
|
||||
saveAsLastTriggerOnSnapshot = false
|
||||
saveAsLastTakePositionSnapshot = false
|
||||
addToSnapshots = false
|
||||
|
||||
let announcementsToBeMade = []
|
||||
let candle = candles[currentCandleIndex];
|
||||
|
||||
@@ -767,7 +823,9 @@
|
||||
if (initialDefinition.positionSize !== undefined) {
|
||||
if (initialDefinition.positionSize.formula !== undefined) {
|
||||
try {
|
||||
positionSize = eval(initialDefinition.positionSize.formula.code);
|
||||
let code = initialDefinition.positionSize.formula.code
|
||||
positionSize = eval(code);
|
||||
addCodeToSnapshot(code)
|
||||
} catch (err) {
|
||||
initialDefinition.positionSize.formula.error = err.message
|
||||
}
|
||||
@@ -794,7 +852,9 @@
|
||||
if (initialDefinition.positionRate !== undefined) {
|
||||
if (initialDefinition.positionRate.formula !== undefined) {
|
||||
try {
|
||||
let code = initialDefinition.positionRate.formula.code
|
||||
positionRate = eval(initialDefinition.positionRate.formula.code);
|
||||
addCodeToSnapshot(code)
|
||||
} catch (err) {
|
||||
initialDefinition.positionRate.formula.error = err.message
|
||||
}
|
||||
@@ -821,7 +881,9 @@
|
||||
|
||||
if (phase.formula !== undefined) {
|
||||
try {
|
||||
formulaValue = eval(phase.formula.code);
|
||||
let code = phase.formula.code
|
||||
formulaValue = eval(code);
|
||||
addCodeToSnapshot(code)
|
||||
if (formulaValue === Infinity) {
|
||||
formulaError = "Formula evaluates to Infinity."
|
||||
formulaValue = MAX_STOP_LOSS_VALUE
|
||||
@@ -910,7 +972,9 @@
|
||||
|
||||
if (phase.formula !== undefined) {
|
||||
try {
|
||||
formulaValue = eval(phase.formula.code);
|
||||
let code = phase.formula.code
|
||||
formulaValue = eval(code);
|
||||
addCodeToSnapshot(code)
|
||||
if (formulaValue === Infinity) {
|
||||
formulaValue = MAX_TAKE_PROFIT_VALUE
|
||||
if (takeProfitStage === 'Open Stage') {
|
||||
@@ -1007,7 +1071,9 @@
|
||||
|
||||
if (phase.formula !== undefined) {
|
||||
try {
|
||||
formulaValue = eval(phase.formula.code);
|
||||
let code = phase.formula.code
|
||||
formulaValue = eval(code);
|
||||
addCodeToSnapshot(code)
|
||||
if (formulaValue === Infinity) {
|
||||
formulaError = ""
|
||||
formulaValue = MAX_STOP_LOSS_VALUE
|
||||
@@ -1096,7 +1162,9 @@
|
||||
|
||||
if (phase.formula !== undefined) {
|
||||
try {
|
||||
formulaValue = eval(phase.formula.code);
|
||||
let code = phase.formula.code
|
||||
formulaValue = eval(code);
|
||||
addCodeToSnapshot(code)
|
||||
if (formulaValue === Infinity) {
|
||||
formulaError = "Formula evaluates to Infinity."
|
||||
formulaValue = MAX_TAKE_PROFIT_VALUE
|
||||
@@ -1181,7 +1249,9 @@
|
||||
let value
|
||||
|
||||
try {
|
||||
value = eval(node.code);
|
||||
let code = node.code
|
||||
value = eval(code);
|
||||
addCodeToSnapshot(code)
|
||||
} catch (err) {
|
||||
/*
|
||||
One possible error is that the conditions references a .previous that is undefined. For this
|
||||
@@ -1262,6 +1332,11 @@
|
||||
|
||||
for (let j = 0; j < tradingSystem.strategies.length; j++) {
|
||||
|
||||
if (
|
||||
strategyStage !== 'No Stage' ||
|
||||
currentStrategyIndex !== -1
|
||||
) {continue}
|
||||
|
||||
let strategy = tradingSystem.strategies[j];
|
||||
|
||||
let triggerStage = strategy.triggerStage
|
||||
@@ -1273,7 +1348,10 @@
|
||||
for (let k = 0; k < triggerStage.triggerOn.situations.length; k++) {
|
||||
|
||||
let situation = triggerStage.triggerOn.situations[k];
|
||||
let passed = true;
|
||||
let passed
|
||||
if (situation.conditions.length > 0) {
|
||||
passed = true
|
||||
}
|
||||
|
||||
for (let m = 0; m < situation.conditions.length; m++) {
|
||||
|
||||
@@ -1298,6 +1376,7 @@
|
||||
currentStrategy.beginRate = candle.min;
|
||||
currentStrategy.endRate = candle.min; // In case the strategy does not get exited
|
||||
currentStrategy.triggerOnSituation = situation.name
|
||||
currentStrategy.name = strategy.name
|
||||
|
||||
if (processingDailyFiles) {
|
||||
if (positionedAtYesterday) {
|
||||
@@ -1307,6 +1386,7 @@
|
||||
yesterday.currentStrategy.beginRate = currentStrategy.beginRate;
|
||||
yesterday.currentStrategy.endRate = currentStrategy.endRate;
|
||||
yesterday.currentStrategy.triggerOnSituation = currentStrategy.triggerOnSituation;
|
||||
yesterday.currentStrategy.name = currentStrategy.name;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1319,6 +1399,7 @@
|
||||
}
|
||||
|
||||
checkAnnouncements(triggerStage.triggerOn)
|
||||
saveAsLastTriggerOnSnapshot = true
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> Switching to Trigger Stage because conditions at Trigger On Event were met."); }
|
||||
break;
|
||||
@@ -1344,7 +1425,10 @@
|
||||
for (let k = 0; k < triggerStage.triggerOff.situations.length; k++) {
|
||||
|
||||
let situation = triggerStage.triggerOff.situations[k];
|
||||
let passed = true;
|
||||
let passed
|
||||
if (situation.conditions.length > 0) {
|
||||
passed = true
|
||||
}
|
||||
|
||||
for (let m = 0; m < situation.conditions.length; m++) {
|
||||
|
||||
@@ -1411,7 +1495,10 @@
|
||||
for (let k = 0; k < triggerStage.takePosition.situations.length; k++) {
|
||||
|
||||
let situation = triggerStage.takePosition.situations[k];
|
||||
let passed = true;
|
||||
let passed
|
||||
if (situation.conditions.length > 0) {
|
||||
passed = true
|
||||
}
|
||||
|
||||
for (let m = 0; m < situation.conditions.length; m++) {
|
||||
|
||||
@@ -1452,6 +1539,7 @@
|
||||
currentTrade.takePositionSituation = situation.name
|
||||
|
||||
checkAnnouncements(triggerStage.takePosition)
|
||||
saveAsLastTakePositionSnapshot = true
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> Conditions at the Take Position Event were met."); }
|
||||
break;
|
||||
@@ -1513,7 +1601,10 @@
|
||||
for (let k = 0; k < nextPhaseEvent.situations.length; k++) {
|
||||
|
||||
let situation = nextPhaseEvent.situations[k];
|
||||
let passed = true;
|
||||
let passed
|
||||
if (situation.conditions.length > 0) {
|
||||
passed = true
|
||||
}
|
||||
|
||||
for (let m = 0; m < situation.conditions.length; m++) {
|
||||
|
||||
@@ -1559,7 +1650,10 @@
|
||||
for (let k = 0; k < moveToPhaseEvent.situations.length; k++) {
|
||||
|
||||
let situation = moveToPhaseEvent.situations[k];
|
||||
let passed = true;
|
||||
let passed
|
||||
if (situation.conditions.length > 0) {
|
||||
passed = true
|
||||
}
|
||||
|
||||
for (let m = 0; m < situation.conditions.length; m++) {
|
||||
|
||||
@@ -1707,7 +1801,10 @@
|
||||
for (let k = 0; k < nextPhaseEvent.situations.length; k++) {
|
||||
|
||||
let situation = nextPhaseEvent.situations[k];
|
||||
let passed = true;
|
||||
let passed
|
||||
if (situation.conditions.length > 0) {
|
||||
passed = true
|
||||
}
|
||||
|
||||
for (let m = 0; m < situation.conditions.length; m++) {
|
||||
|
||||
@@ -1753,7 +1850,10 @@
|
||||
for (let k = 0; k < moveToPhaseEvent.situations.length; k++) {
|
||||
|
||||
let situation = moveToPhaseEvent.situations[k];
|
||||
let passed = true;
|
||||
let passed
|
||||
if (situation.conditions.length > 0) {
|
||||
passed = true
|
||||
}
|
||||
|
||||
for (let m = 0; m < situation.conditions.length; m++) {
|
||||
|
||||
@@ -1999,6 +2099,7 @@
|
||||
currentTrade.endRate = closeRate;
|
||||
|
||||
closePositionNow = true;
|
||||
addToSnapshots = true
|
||||
|
||||
if (processingDailyFiles) {
|
||||
if (positionedAtYesterday) {
|
||||
@@ -2071,6 +2172,7 @@
|
||||
currentTrade.endRate = closeRate;
|
||||
|
||||
closePositionNow = true;
|
||||
addToSnapshots = true
|
||||
|
||||
if (processingDailyFiles) {
|
||||
if (positionedAtYesterday) {
|
||||
@@ -2186,6 +2288,7 @@
|
||||
}
|
||||
|
||||
takePositionAtSimulation()
|
||||
|
||||
return
|
||||
|
||||
function putOpeningOrder() {
|
||||
@@ -2243,7 +2346,7 @@
|
||||
if (baseAsset === bot.market.baseAsset) {
|
||||
orderSide = "sell"
|
||||
|
||||
orderPrice = tradePositionRate - 100 // This is going to be ingnored at the Exchange API for now since we only put market orders.
|
||||
orderPrice = tradePositionRate
|
||||
|
||||
amountA = tradePositionSize * orderPrice
|
||||
amountB = tradePositionSize
|
||||
@@ -2251,7 +2354,7 @@
|
||||
} else {
|
||||
orderSide = "buy"
|
||||
|
||||
orderPrice = tradePositionRate // This is going to be ingnored at the Exchange API for now since we only put market orders.
|
||||
orderPrice = tradePositionRate
|
||||
|
||||
amountA = tradePositionSize
|
||||
amountB = tradePositionSize / orderPrice
|
||||
@@ -2845,7 +2948,8 @@
|
||||
number: 0,
|
||||
beginRate: 0,
|
||||
endRate: 0,
|
||||
triggerOnSituation: ''
|
||||
triggerOnSituation: '',
|
||||
name: ''
|
||||
}
|
||||
|
||||
if (processingDailyFiles) {
|
||||
@@ -2857,7 +2961,8 @@
|
||||
number: 0,
|
||||
beginRate: 0,
|
||||
endRate: 0,
|
||||
triggerOnSituation: ''
|
||||
triggerOnSituation: '',
|
||||
name: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2880,6 +2985,57 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* Snapshots Management (before we generate the trade record and delete that info) */
|
||||
if (saveAsLastTriggerOnSnapshot === true) {
|
||||
snapshots.lastTriggerOn = snapshotDataRecord
|
||||
saveAsLastTriggerOnSnapshot = false
|
||||
}
|
||||
|
||||
if (saveAsLastTakePositionSnapshot === true) {
|
||||
snapshots.lastTakePosition = snapshotDataRecord
|
||||
saveAsLastTakePositionSnapshot = false
|
||||
}
|
||||
|
||||
if (addToSnapshots === true) {
|
||||
let closeValues = [
|
||||
roundtrips, // Trade Number
|
||||
(new Date(candle.begin)).toISOString(), // Datetime
|
||||
tradingSystem.strategies[currentStrategyIndex].name, // Strategy
|
||||
currentStrategy.triggerOnSituation, // Trigger On Situation
|
||||
currentTrade.takePositionSituation, // Take Position Situation
|
||||
hitOrFial(), // Result
|
||||
lastTradeROI, // ROI
|
||||
simulationRecord.type.replace(/"/g, '') // Exit Type
|
||||
]
|
||||
|
||||
function hitOrFial() {
|
||||
if (lastTradeROI > 0) { return 'HIT' } else { return 'FAIL' }
|
||||
}
|
||||
|
||||
if (positionedAtYesterday === false) {
|
||||
snapshots.triggerOn.push(closeValues.concat(snapshots.lastTriggerOn))
|
||||
snapshots.takePosition.push(closeValues.concat(snapshots.lastTakePosition))
|
||||
}
|
||||
snapshots.lastTriggerOn = undefined
|
||||
snapshots.lastTakePosition = undefined
|
||||
addToSnapshots = false
|
||||
}
|
||||
|
||||
let closeHeaders = ['Trade Number', 'Close Datetime', 'Strategy', 'Trigger On Situation', 'Take Position Situation', 'Result', 'ROI', 'Exit Type']
|
||||
if (snapshots.headers === undefined) {
|
||||
snapshots.headers = closeHeaders.concat(JSON.parse(JSON.stringify(snapshotLoopHeaders)))
|
||||
}
|
||||
|
||||
if (processingDailyFiles) {
|
||||
if (positionedAtYesterday) {
|
||||
yesterday.snapshots.headers = snapshots.headers;
|
||||
yesterday.snapshots.triggerOn = snapshots.triggerOn;
|
||||
yesterday.snapshots.takePosition = snapshots.takePosition;
|
||||
yesterday.snapshots.lastTriggerOn = snapshots.lastTriggerOn;
|
||||
yesterday.snapshots.lastTakePosition = snapshots.lastTakePosition;
|
||||
}
|
||||
}
|
||||
|
||||
/* Prepare the information for the Trades File */
|
||||
if (currentTrade.begin !== 0 && currentTrade.end !== 0) {
|
||||
|
||||
@@ -2914,7 +3070,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
makeAnnoucements() // After everything at the simulation level was done, we will do the annoucements that are pending.
|
||||
/* After everything at the simulation level was done, we will do the annoucements that are pending.*/
|
||||
makeAnnoucements()
|
||||
}
|
||||
|
||||
function checkAnnouncements(node, value) {
|
||||
@@ -3005,10 +3162,65 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addCodeToSnapshot(code) {
|
||||
if (code === undefined) { return }
|
||||
|
||||
try {
|
||||
let instructionsArray = code.split(' ')
|
||||
for (let i = 0; i < instructionsArray.length; i++) {
|
||||
let instruction = instructionsArray[i]
|
||||
instruction = instruction.replace('(', '')
|
||||
instruction = instruction.replace(')', '')
|
||||
instruction = instruction.replace(/</g, '')
|
||||
instruction = instruction.replace(/>/g, '')
|
||||
instruction = instruction.replace(/<=/g, '')
|
||||
instruction = instruction.replace(/>=/g, '')
|
||||
instruction = instruction.replace(/!=/g, '')
|
||||
instruction = instruction.replace(/!==/g, '')
|
||||
instruction = instruction.replace(/==/g, '')
|
||||
instruction = instruction.replace(/===/g, '')
|
||||
instruction = instruction.replace(/{/g, '')
|
||||
instruction = instruction.replace(/}/g, '')
|
||||
if (instruction.indexOf('chart') >= 0) {
|
||||
let parts = instruction.split('.')
|
||||
let timeFrame = parts[1]
|
||||
let product = parts[2]
|
||||
let property
|
||||
checkPrevious(3)
|
||||
function checkPrevious(index) {
|
||||
property = parts[index]
|
||||
if (property === 'previous') {
|
||||
product = product + '.previous'
|
||||
checkPrevious(index + 1)
|
||||
}
|
||||
}
|
||||
|
||||
// Example: chart.at01hs.popularSMA.sma200 - chart.at01hs.popularSMA.sma100 < 10
|
||||
if (timeFrame !== 'atAnyTimeFrame') {
|
||||
timeFrame = timeFrame.substring(2, 4) + '-' + timeFrame.substring(4, 7)
|
||||
}
|
||||
let key = timeFrame + '-' + product + '-' + property
|
||||
let existingKey = snapshotKeys.get(key)
|
||||
|
||||
if (existingKey === undefined) {// means that at the current loop this property of this product was not used before.
|
||||
snapshotKeys.set(key, key)
|
||||
snapshotLoopHeaders.push(key)
|
||||
|
||||
let value = eval(instruction)
|
||||
snapshotDataRecord.push(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] runSimulation -> addCodeToSnapshot -> code = " + code);
|
||||
logger.write(MODULE_NAME, "[ERROR] runSimulation -> addCodeToSnapshot -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function controlLoop() {
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> controlLoop -> Entering function."); }
|
||||
|
||||
@@ -3047,6 +3259,14 @@
|
||||
|
||||
if (lastCandle.end === lastInstantOfTheDay) {
|
||||
|
||||
interExecutionMemory.snapshots = {
|
||||
headers: yesterday.snapshots.headers,
|
||||
triggerOn: yesterday.snapshots.triggerOn,
|
||||
takePosition: yesterday.snapshots.takePosition,
|
||||
lastTriggerOn: yesterday.snapshots.lastTriggerOn,
|
||||
lastTakePosition: yesterday.snapshots.lastTakePosition
|
||||
}
|
||||
|
||||
interExecutionMemory.stopLoss = yesterday.stopLoss
|
||||
interExecutionMemory.takeProfit = yesterday.takeProfit
|
||||
|
||||
@@ -3072,7 +3292,8 @@
|
||||
number: yesterday.currentStrategy.number,
|
||||
beginRate: yesterday.currentStrategy.beginRate,
|
||||
endRate: yesterday.currentStrategy.endRate,
|
||||
triggerOnSituation: yesterday.currentStrategy.triggerOnSituation
|
||||
triggerOnSituation: yesterday.currentStrategy.triggerOnSituation,
|
||||
name: yesterday.currentStrategy.name
|
||||
}
|
||||
|
||||
interExecutionMemory.currentTrade = {
|
||||
@@ -3114,7 +3335,7 @@
|
||||
|
||||
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> callback -> recordsArray.length = " + recordsArray.length); }
|
||||
|
||||
callback(tradingSystem, recordsArray, conditionsArray, strategiesArray, tradesArray);
|
||||
callback(tradingSystem, recordsArray, conditionsArray, strategiesArray, tradesArray, snapshots.headers, snapshots.triggerOn, snapshots.takePosition);
|
||||
}
|
||||
|
||||
function getElement(pArray, currentCandle, datasetName) {
|
||||
@@ -3156,6 +3377,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
catch (err) {
|
||||
logger.write(MODULE_NAME, "[ERROR] runSimulation -> err = " + err.stack);
|
||||
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
|
||||
|
||||
+23
-1
@@ -333,9 +333,21 @@ function exportKeywordsToPackageJson (exchanges) {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
function exportEverything () {
|
||||
function flatten (nested, result = []) {
|
||||
for (const key in nested) {
|
||||
result.push (key)
|
||||
if (Object.keys (nested[key]).length)
|
||||
flatten (nested[key], result)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
function exportEverything () {
|
||||
const ids = getIncludedExchangeIds ()
|
||||
const errorHierarchy = require ('../js/base/errorHierarchy.js')
|
||||
const flat = flatten (errorHierarchy)
|
||||
flat.push ('error_hierarchy')
|
||||
|
||||
const replacements = [
|
||||
{
|
||||
@@ -353,6 +365,16 @@ function exportEverything () {
|
||||
regex: /(?:from ccxt\.[^\.]+ import [^\s]+\s+\# noqa\: F401[\r]?[\n])+[\r]?[\n]exchanges/,
|
||||
replacement: ids.map (id => ('from ccxt.' + id + ' import ' + id).padEnd (60) + '# noqa: F401').join ("\n") + "\n\nexchanges",
|
||||
},
|
||||
{
|
||||
file: './python/ccxt/__init__.py',
|
||||
regex: /(?:from ccxt\.base\.errors import [^\s]+\s+\# noqa\: F401[\r]?[\n])+[\r]?[\n]/,
|
||||
replacement: flat.map (error => ('from ccxt.base.errors' + ' import ' + error).padEnd (60) + '# noqa: F401').join ("\n") + "\n\n",
|
||||
},
|
||||
{
|
||||
file: './python/ccxt/async_support/__init__.py',
|
||||
regex: /(?:from ccxt\.base\.errors import [^\s]+\s+\# noqa\: F401[\r]?[\n])+[\r]?[\n]/,
|
||||
replacement: flat.map (error => ('from ccxt.base.errors' + ' import ' + error).padEnd (60) + '# noqa: F401').join ("\n") + "\n\n",
|
||||
},
|
||||
{
|
||||
file: './python/ccxt/async_support/__init__.py',
|
||||
regex: /(?:from ccxt\.async_support\.[^\.]+ import [^\s]+\s+\# noqa\: F401[\r]?[\n])+[\r]?[\n]exchanges/,
|
||||
|
||||
+2
@@ -199,6 +199,7 @@ class Transpiler {
|
||||
[ /(^|[^a-zA-Z0-9_])(?:let|const|var)\s/g, '$1' ],
|
||||
[ /Object\.keys\s*\((.*)\)\.length/g, '$1' ],
|
||||
[ /Object\.keys\s*\((.*)\)/g, 'list($1.keys())' ],
|
||||
[ /Object\.values\s*\((.*)\)/g, 'list($1.values())' ],
|
||||
[ /\[([^\]]+)\]\.join\s*\(([^\)]+)\)/g, "$2.join([$1])" ],
|
||||
[ /hash \(([^,]+)\, \'(sha[0-9])\'/g, "hash($1, '$2'" ],
|
||||
[ /hmac \(([^,]+)\, ([^,]+)\, \'(md5)\'/g, 'hmac($1, $2, hashlib.$3' ],
|
||||
@@ -330,6 +331,7 @@ class Transpiler {
|
||||
[ /(^|[^a-zA-Z0-9_])(?:let|const|var)\s/g, '$1' ],
|
||||
[ /Object\.keys\s*\((.*)\)\.length/g, '$1' ],
|
||||
[ /Object\.keys\s*\((.*)\)/g, 'is_array($1) ? array_keys($1) : array()' ],
|
||||
[ /Object\.values\s*\((.*)\)/g, 'is_array($1) ? array_values($1) : array()' ],
|
||||
[ /([^\s]+\s*\(\))\.toString \(\)/g, '(string) $1' ],
|
||||
[ /([^\s]+)\.toString \(\)/g, '(string) $1' ],
|
||||
[ /throw new Error \((.*)\)/g, 'throw new \\Exception($1)' ],
|
||||
|
||||
+2
-3
@@ -35,7 +35,7 @@ const Exchange = require ('./js/base/Exchange')
|
||||
//-----------------------------------------------------------------------------
|
||||
// this is updated by vss.js when building
|
||||
|
||||
const version = '1.25.80'
|
||||
const version = '1.27.45'
|
||||
|
||||
Exchange.ccxtVersion = version
|
||||
|
||||
@@ -44,7 +44,6 @@ Exchange.ccxtVersion = version
|
||||
const exchanges = {
|
||||
'_1btcxe': require ('./js/_1btcxe.js'),
|
||||
'acx': require ('./js/acx.js'),
|
||||
'adara': require ('./js/adara.js'),
|
||||
'anxpro': require ('./js/anxpro.js'),
|
||||
'aofex': require ('./js/aofex.js'),
|
||||
'bcex': require ('./js/bcex.js'),
|
||||
@@ -115,8 +114,8 @@ const exchanges = {
|
||||
'fybse': require ('./js/fybse.js'),
|
||||
'gateio': require ('./js/gateio.js'),
|
||||
'gemini': require ('./js/gemini.js'),
|
||||
'hbtc': require ('./js/hbtc.js'),
|
||||
'hitbtc': require ('./js/hitbtc.js'),
|
||||
'hitbtc2': require ('./js/hitbtc2.js'),
|
||||
'hollaex': require ('./js/hollaex.js'),
|
||||
'huobipro': require ('./js/huobipro.js'),
|
||||
'huobiru': require ('./js/huobiru.js'),
|
||||
|
||||
+4395
-2136
File diff suppressed because it is too large.
Load diff
-1255
File diff suppressed because it is too large.
Load diff
+9
-3
@@ -30,6 +30,7 @@ module.exports = class aofex extends Exchange {
|
||||
'fetchOpenOrders': true,
|
||||
'fetchClosedOrders': true,
|
||||
'fetchClosedOrder': true,
|
||||
'fetchOrderTrades': true,
|
||||
'fetchTradingFee': true,
|
||||
},
|
||||
'timeframes': {
|
||||
@@ -559,7 +560,7 @@ module.exports = class aofex extends Exchange {
|
||||
//
|
||||
const id = this.safeString (trade, 'id');
|
||||
const ctime = this.parse8601 (this.safeString (trade, 'ctime'));
|
||||
const timestamp = this.safeTimestamp (trade, 'ts', ctime);
|
||||
const timestamp = this.safeTimestamp (trade, 'ts', ctime) - 28800000; // 8 hours, adjust to UTC;
|
||||
let symbol = undefined;
|
||||
if ((symbol === undefined) && (market !== undefined)) {
|
||||
symbol = market['symbol'];
|
||||
@@ -725,7 +726,7 @@ module.exports = class aofex extends Exchange {
|
||||
base = market['base'];
|
||||
quote = market['quote'];
|
||||
}
|
||||
const timestamp = this.parse8601 (this.safeString (order, 'ctime'));
|
||||
const timestamp = this.parse8601 (this.safeString (order, 'ctime')) - 28800000; // 8 hours, adjust to UTC
|
||||
const orderType = this.safeString (order, 'type');
|
||||
const type = (orderType === '2') ? 'limit' : 'market';
|
||||
const side = this.safeString (order, 'side');
|
||||
@@ -883,11 +884,16 @@ module.exports = class aofex extends Exchange {
|
||||
return this.parseOrder (order);
|
||||
}
|
||||
|
||||
async fetchOrderTrades (id, symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
||||
const response = await this.fetchClosedOrder (id, symbol, params);
|
||||
return this.safeValue (response, 'trades', []);
|
||||
}
|
||||
|
||||
async fetchOrdersWithMethod (method, symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
||||
await this.loadMarkets ();
|
||||
const request = {
|
||||
// 'from': 'BM7442641584965237751ZMAKJ5', // query start order_sn
|
||||
// 'direct': 'prev', // next
|
||||
'direct': 'prev', // next
|
||||
};
|
||||
let market = undefined;
|
||||
if (symbol !== undefined) {
|
||||
|
||||
+43
-15
@@ -288,8 +288,9 @@ module.exports = class Exchange {
|
||||
const config = deepExtend (this.describe (), userConfig)
|
||||
|
||||
// merge to this
|
||||
for (const [property, value] of Object.entries (config))
|
||||
for (const [property, value] of Object.entries (config)) {
|
||||
this[property] = deepExtend (this[property], value)
|
||||
}
|
||||
|
||||
if (!this.httpAgent) {
|
||||
this.httpAgent = defaultFetch.http ? new defaultFetch.http.Agent ({ 'keepAlive': true }) : undefined
|
||||
@@ -304,13 +305,15 @@ module.exports = class Exchange {
|
||||
this['has' + capitalize (k)] = !!this.has[k] // converts 'emulated' to true
|
||||
}
|
||||
|
||||
if (this.api)
|
||||
if (this.api) {
|
||||
this.defineRestApi (this.api, 'request')
|
||||
}
|
||||
|
||||
this.initRestRateLimiter ()
|
||||
|
||||
if (this.markets)
|
||||
if (this.markets) {
|
||||
this.setMarkets (this.markets)
|
||||
}
|
||||
}
|
||||
|
||||
defaults () {
|
||||
@@ -342,20 +345,23 @@ module.exports = class Exchange {
|
||||
|
||||
checkAddress (address) {
|
||||
|
||||
if (address === undefined)
|
||||
if (address === undefined) {
|
||||
throw new InvalidAddress (this.id + ' address is undefined')
|
||||
}
|
||||
|
||||
// check the address is not the same letter like 'aaaaa' nor too short nor has a space
|
||||
if ((unique (address).length === 1) || address.length < this.minFundingAddressLength || address.includes (' '))
|
||||
if ((unique (address).length === 1) || address.length < this.minFundingAddressLength || address.includes (' ')) {
|
||||
throw new InvalidAddress (this.id + ' address is invalid or has less than ' + this.minFundingAddressLength.toString () + ' characters: "' + this.json (address) + '"')
|
||||
}
|
||||
|
||||
return address
|
||||
}
|
||||
|
||||
initRestRateLimiter () {
|
||||
|
||||
if (this.rateLimit === undefined)
|
||||
if (this.rateLimit === undefined) {
|
||||
throw new Error (this.id + '.rateLimit property is not configured')
|
||||
}
|
||||
|
||||
this.tokenBucket = this.extend ({
|
||||
delay: 1,
|
||||
@@ -386,15 +392,17 @@ module.exports = class Exchange {
|
||||
const promise =
|
||||
fetchImplementation (url, this.extend (params, this.fetchOptions))
|
||||
.catch ((e) => {
|
||||
if (isNode)
|
||||
if (isNode) {
|
||||
throw new ExchangeNotAvailable ([ this.id, method, url, e.type, e.message ].join (' '))
|
||||
}
|
||||
throw e // rethrow all unknown errors
|
||||
})
|
||||
.then (response => this.handleRestResponse (response, url, method, headers, body))
|
||||
.then ((response) => this.handleRestResponse (response, url, method, headers, body))
|
||||
|
||||
return timeout (this.timeout, promise).catch ((e) => {
|
||||
if (e instanceof TimedOut)
|
||||
if (e instanceof TimedOut) {
|
||||
throw new RequestTimeout (this.id + ' ' + method + ' ' + url + ' request timed out (' + this.timeout + ' ms)')
|
||||
}
|
||||
throw e
|
||||
})
|
||||
}
|
||||
@@ -442,16 +450,20 @@ module.exports = class Exchange {
|
||||
let underscore = type + '_' + lowercaseMethod + '_' + underscoreSuffix
|
||||
|
||||
if ('suffixes' in options) {
|
||||
if ('camelcase' in options['suffixes'])
|
||||
if ('camelcase' in options['suffixes']) {
|
||||
camelcase += options['suffixes']['camelcase']
|
||||
if ('underscore' in options.suffixes)
|
||||
}
|
||||
if ('underscore' in options.suffixes) {
|
||||
underscore += options['suffixes']['underscore']
|
||||
}
|
||||
}
|
||||
|
||||
if ('underscore_suffix' in options)
|
||||
if ('underscore_suffix' in options) {
|
||||
underscore += options.underscoreSuffix;
|
||||
if ('camelcase_suffix' in options)
|
||||
}
|
||||
if ('camelcase_suffix' in options) {
|
||||
camelcase += options.camelcaseSuffix;
|
||||
}
|
||||
|
||||
let partial = async params => this[methodName] (path, type, uppercaseMethod, params || {})
|
||||
|
||||
@@ -594,7 +606,7 @@ module.exports = class Exchange {
|
||||
getResponseHeaders (response) {
|
||||
const result = {}
|
||||
response.headers.forEach ((value, key) => {
|
||||
key = key.split ('-').map (word => capitalize (word)).join ('-')
|
||||
key = key.split ('-').map ((word) => capitalize (word)).join ('-')
|
||||
result[key] = value
|
||||
})
|
||||
return result
|
||||
@@ -632,7 +644,7 @@ module.exports = class Exchange {
|
||||
}
|
||||
|
||||
setMarkets (markets, currencies = undefined) {
|
||||
const values = Object.values (markets).map (market => deepExtend ({
|
||||
const values = Object.values (markets).map ((market) => deepExtend ({
|
||||
'limits': this.limits,
|
||||
'precision': this.precision,
|
||||
}, this.fees['trading'], market))
|
||||
@@ -803,6 +815,22 @@ module.exports = class Exchange {
|
||||
throw new NotSupported (this.id + ' fetchOrder not supported yet');
|
||||
}
|
||||
|
||||
fetchUnifiedOrder (order, params = {}) {
|
||||
return this.fetchOrder (this.safeValue (order, 'id'), this.safeValue (order, 'symbol'), params);
|
||||
}
|
||||
|
||||
createOrder (symbol, type, side, amount, price = undefined, params = {}) {
|
||||
throw new NotSupported (this.id + ' createOrder not supported yet');
|
||||
}
|
||||
|
||||
cancelOrder (id, symbol = undefined, params = {}) {
|
||||
throw new NotSupported (this.id + ' cancelOrder not supported yet');
|
||||
}
|
||||
|
||||
cancelUnifiedOrder (order, params = {}) {
|
||||
return this.cancelOrder (this.safeValue (order, 'id'), this.safeValue (order, 'symbol'), params);
|
||||
}
|
||||
|
||||
fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
||||
throw new NotSupported (this.id + ' fetchOrders not supported yet');
|
||||
}
|
||||
|
||||
+11
-7
@@ -45,23 +45,27 @@ function numberToString (x) { // avoids scientific notation for too large and to
|
||||
|
||||
if (typeof x === 'string') return x
|
||||
|
||||
const s = x.toString ()
|
||||
if (Math.abs (x) < 1.0) {
|
||||
const s = x.toString ()
|
||||
const e = parseInt (s.split ('e-')[1])
|
||||
const neg = (s[0] === '-')
|
||||
if (e) {
|
||||
x *= Math.pow (10, e - 1)
|
||||
x = (neg ? '-' : '') + '0.' + (new Array (e)).join ('0') + x.toString ().substring (neg ? 3 : 2)
|
||||
return x
|
||||
}
|
||||
} else {
|
||||
let e = parseInt (x.toString ().split ('+')[1])
|
||||
if (e > 20) {
|
||||
e -= 20
|
||||
x /= Math.pow (10, e)
|
||||
x += (new Array (e + 1)).join ('0')
|
||||
const parts = s.split ('e')
|
||||
if (parts[1]) {
|
||||
let e = parseInt (parts[1])
|
||||
const m = parts[0].split ('.')
|
||||
if (m[1]) {
|
||||
e -= m[1].length
|
||||
}
|
||||
return m[0] + m[1] + (new Array (e + 1)).join ('0')
|
||||
}
|
||||
}
|
||||
return x.toString ()
|
||||
return s;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
+106
-34
@@ -3,7 +3,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const Exchange = require ('./base/Exchange');
|
||||
const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, InvalidOrder, DDoSProtection, InvalidNonce, AuthenticationError, InvalidAddress, RateLimitExceeded, PermissionDenied } = require ('./base/errors');
|
||||
const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, InvalidOrder, DDoSProtection, InvalidNonce, AuthenticationError, InvalidAddress, RateLimitExceeded, PermissionDenied, NotSupported } = require ('./base/errors');
|
||||
const { ROUND, TRUNCATE } = require ('./base/functions/number');
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -37,6 +37,7 @@ module.exports = class binance extends Exchange {
|
||||
'fetchTransactions': false,
|
||||
'fetchTradingFee': true,
|
||||
'fetchTradingFees': true,
|
||||
'cancelAllOrders': true,
|
||||
},
|
||||
'timeframes': {
|
||||
'1m': '1m',
|
||||
@@ -57,6 +58,10 @@ module.exports = class binance extends Exchange {
|
||||
},
|
||||
'urls': {
|
||||
'logo': 'https://user-images.githubusercontent.com/1294454/29604020-d5483cdc-87ee-11e7-94c7-d1a8d9169293.jpg',
|
||||
'test': {
|
||||
'fapiPublic': 'https://testnet.binancefuture.com/fapi/v1',
|
||||
'fapiPrivate': 'https://testnet.binancefuture.com/fapi/v1',
|
||||
},
|
||||
'api': {
|
||||
'web': 'https://www.binance.com',
|
||||
'wapi': 'https://api.binance.com/wapi/v3',
|
||||
@@ -130,6 +135,8 @@ module.exports = class binance extends Exchange {
|
||||
'lending/union/purchaseRecord',
|
||||
'lending/union/redemptionRecord',
|
||||
'lending/union/interestHistory',
|
||||
'lending/project/list',
|
||||
'lending/project/position/list',
|
||||
],
|
||||
'post': [
|
||||
'asset/dust',
|
||||
@@ -146,6 +153,7 @@ module.exports = class binance extends Exchange {
|
||||
'userDataStream',
|
||||
'futures/transfer',
|
||||
// lending
|
||||
'lending/customizedFixed/purchase',
|
||||
'lending/daily/purchase',
|
||||
'lending/daily/redeem',
|
||||
],
|
||||
@@ -211,6 +219,8 @@ module.exports = class binance extends Exchange {
|
||||
'income',
|
||||
],
|
||||
'post': [
|
||||
'batchOrders',
|
||||
'positionSide/dual',
|
||||
'positionMargin',
|
||||
'marginType',
|
||||
'order',
|
||||
@@ -221,6 +231,7 @@ module.exports = class binance extends Exchange {
|
||||
'listenKey',
|
||||
],
|
||||
'delete': [
|
||||
'batchOrders',
|
||||
'order',
|
||||
'allOpenOrders',
|
||||
'listenKey',
|
||||
@@ -267,6 +278,7 @@ module.exports = class binance extends Exchange {
|
||||
'order/test',
|
||||
],
|
||||
'delete': [
|
||||
'openOrders', // added on 2020-04-25 for canceling all open orders per symbol
|
||||
'orderList', // oco
|
||||
'order',
|
||||
],
|
||||
@@ -289,7 +301,6 @@ module.exports = class binance extends Exchange {
|
||||
'fetchTradesMethod': 'publicGetAggTrades', // publicGetTrades, publicGetHistoricalTrades
|
||||
'fetchTickersMethod': 'publicGetTicker24hr',
|
||||
'defaultTimeInForce': 'GTC', // 'GTC' = Good To Cancel (default), 'IOC' = Immediate Or Cancel
|
||||
'defaultLimitOrderType': 'limit', // or 'limit_maker'
|
||||
'defaultType': 'spot', // 'spot', 'future'
|
||||
'hasAlreadyAuthenticatedSuccessfully': false,
|
||||
'warnOnFetchOpenOrdersWithoutSymbol': true,
|
||||
@@ -326,6 +337,32 @@ module.exports = class binance extends Exchange {
|
||||
});
|
||||
}
|
||||
|
||||
setSandboxMode (enabled) {
|
||||
if (enabled) { // eslint-disable-line no-extra-boolean-cast
|
||||
if ('test' in this.urls) {
|
||||
const type = this.safeString (this.options, 'defaultType', 'spot');
|
||||
if (type !== 'future') {
|
||||
throw new NotSupported (this.id + ' does not have a sandbox URL for ' + type + " markets, set exchange.options['defaultType'] = 'future' or don't use the sandbox for " + this.id);
|
||||
}
|
||||
if (typeof this.urls['api'] === 'string') {
|
||||
this.urls['api_backup'] = this.urls['api'];
|
||||
this.urls['api'] = this.urls['test'];
|
||||
} else {
|
||||
this.urls['api_backup'] = this.extend ({}, this.urls['api']);
|
||||
this.urls['api'] = this.extend ({}, this.urls['test']);
|
||||
}
|
||||
} else {
|
||||
throw new NotSupported (this.id + ' does not have a sandbox URL');
|
||||
}
|
||||
} else if ('api_backup' in this.urls) {
|
||||
if (typeof this.urls['api'] === 'string') {
|
||||
this.urls['api'] = this.urls['api_backup'];
|
||||
} else {
|
||||
this.urls['api'] = this.extend ({}, this.urls['api_backup']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nonce () {
|
||||
return this.milliseconds () - this.options['timeDifference'];
|
||||
}
|
||||
@@ -476,7 +513,7 @@ module.exports = class binance extends Exchange {
|
||||
'max': undefined,
|
||||
},
|
||||
'cost': {
|
||||
'min': -1 * Math.log10 (precision['amount']),
|
||||
'min': undefined,
|
||||
'max': undefined,
|
||||
},
|
||||
},
|
||||
@@ -720,7 +757,7 @@ module.exports = class binance extends Exchange {
|
||||
|
||||
async fetchBidsAsks (symbols = undefined, params = {}) {
|
||||
await this.loadMarkets ();
|
||||
const defaultType = this.safeString2 (this.options, 'fetchOpenOrders', 'defaultType', 'spot');
|
||||
const defaultType = this.safeString2 (this.options, 'fetchBidsAsks', 'defaultType', 'spot');
|
||||
const type = this.safeString (params, 'type', defaultType);
|
||||
const query = this.omit (params, 'type');
|
||||
const method = (type === 'spot') ? 'publicGetTickerBookTicker' : 'fapiPublicGetTickerBookTicker';
|
||||
@@ -737,12 +774,12 @@ module.exports = class binance extends Exchange {
|
||||
|
||||
parseOHLCV (ohlcv, market = undefined, timeframe = '1m', since = undefined, limit = undefined) {
|
||||
return [
|
||||
ohlcv[0],
|
||||
parseFloat (ohlcv[1]),
|
||||
parseFloat (ohlcv[2]),
|
||||
parseFloat (ohlcv[3]),
|
||||
parseFloat (ohlcv[4]),
|
||||
parseFloat (ohlcv[5]),
|
||||
this.safeInteger (ohlcv, 0),
|
||||
this.safeFloat (ohlcv, 1),
|
||||
this.safeFloat (ohlcv, 2),
|
||||
this.safeFloat (ohlcv, 3),
|
||||
this.safeFloat (ohlcv, 4),
|
||||
this.safeFloat (ohlcv, 5),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -870,6 +907,10 @@ module.exports = class binance extends Exchange {
|
||||
if (market !== undefined) {
|
||||
symbol = market['symbol'];
|
||||
}
|
||||
let cost = undefined;
|
||||
if ((price !== undefined) && (amount !== undefined)) {
|
||||
cost = price * amount;
|
||||
}
|
||||
return {
|
||||
'info': trade,
|
||||
'timestamp': timestamp,
|
||||
@@ -878,11 +919,11 @@ module.exports = class binance extends Exchange {
|
||||
'id': id,
|
||||
'order': orderId,
|
||||
'type': undefined,
|
||||
'takerOrMaker': takerOrMaker,
|
||||
'side': side,
|
||||
'takerOrMaker': takerOrMaker,
|
||||
'price': price,
|
||||
'amount': amount,
|
||||
'cost': price * amount,
|
||||
'cost': cost,
|
||||
'fee': fee,
|
||||
};
|
||||
}
|
||||
@@ -1180,6 +1221,8 @@ module.exports = class binance extends Exchange {
|
||||
} else if (uppercaseType === 'STOP') {
|
||||
stopPriceIsRequired = true;
|
||||
priceIsRequired = true;
|
||||
} else if (uppercaseType === 'STOP_MARKET') {
|
||||
stopPriceIsRequired = true;
|
||||
}
|
||||
if (priceIsRequired) {
|
||||
if (price === undefined) {
|
||||
@@ -1339,6 +1382,27 @@ module.exports = class binance extends Exchange {
|
||||
return this.parseOrder (response);
|
||||
}
|
||||
|
||||
async cancelAllOrders (symbol = undefined, params = {}) {
|
||||
if (symbol === undefined) {
|
||||
throw new ArgumentsRequired (this.id + ' cancelAllOrders requires a symbol argument');
|
||||
}
|
||||
await this.loadMarkets ();
|
||||
const market = this.market (symbol);
|
||||
const request = {
|
||||
'symbol': market['id'],
|
||||
};
|
||||
const defaultType = this.safeString2 (this.options, 'cancelAllOrders', 'defaultType', 'spot');
|
||||
const type = this.safeString (params, 'type', defaultType);
|
||||
const query = this.omit (params, 'type');
|
||||
const method = (type === 'spot') ? 'privateDeleteOpenOrders' : 'fapiPrivateDeleteAllOpenOrders';
|
||||
const response = await this[method] (this.extend (request, query));
|
||||
if (Array.isArray (response)) {
|
||||
return this.parseOrders (response, market);
|
||||
} else {
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
||||
if (symbol === undefined) {
|
||||
throw new ArgumentsRequired (this.id + ' fetchMyTrades requires a symbol argument');
|
||||
@@ -1571,10 +1635,7 @@ module.exports = class binance extends Exchange {
|
||||
}
|
||||
|
||||
parseTransactionStatusByType (status, type = undefined) {
|
||||
if (type === undefined) {
|
||||
return status;
|
||||
}
|
||||
const statuses = {
|
||||
const statusesByType = {
|
||||
'deposit': {
|
||||
'0': 'pending',
|
||||
'1': 'ok',
|
||||
@@ -1589,32 +1650,38 @@ module.exports = class binance extends Exchange {
|
||||
'6': 'ok', // Completed
|
||||
},
|
||||
};
|
||||
return (status in statuses[type]) ? statuses[type][status] : status;
|
||||
const statuses = this.safeValue (statusesByType, type, {});
|
||||
return this.safeString (statuses, status, status);
|
||||
}
|
||||
|
||||
parseTransaction (transaction, currency = undefined) {
|
||||
//
|
||||
// fetchDeposits
|
||||
// { insertTime: 1517425007000,
|
||||
// amount: 0.3,
|
||||
// address: "0x0123456789abcdef",
|
||||
// addressTag: "",
|
||||
// txId: "0x0123456789abcdef",
|
||||
// asset: "ETH",
|
||||
// status: 1 }
|
||||
//
|
||||
// {
|
||||
// insertTime: 1517425007000,
|
||||
// amount: 0.3,
|
||||
// address: "0x0123456789abcdef",
|
||||
// addressTag: "",
|
||||
// txId: "0x0123456789abcdef",
|
||||
// asset: "ETH",
|
||||
// status: 1
|
||||
// }
|
||||
//
|
||||
// fetchWithdrawals
|
||||
//
|
||||
// { amount: 14,
|
||||
// address: "0x0123456789abcdef...",
|
||||
// {
|
||||
// amount: 14,
|
||||
// address: "0x0123456789abcdef...",
|
||||
// successTime: 1514489710000,
|
||||
// transactionFee: 0.01,
|
||||
// addressTag: "",
|
||||
// txId: "0x0123456789abcdef...",
|
||||
// id: "0123456789abcdef...",
|
||||
// asset: "ETH",
|
||||
// applyTime: 1514488724000,
|
||||
// status: 6 }
|
||||
// transactionFee: 0.01,
|
||||
// addressTag: "",
|
||||
// txId: "0x0123456789abcdef...",
|
||||
// id: "0123456789abcdef...",
|
||||
// asset: "ETH",
|
||||
// applyTime: 1514488724000,
|
||||
// status: 6
|
||||
// }
|
||||
//
|
||||
const id = this.safeString (transaction, 'id');
|
||||
const address = this.safeString (transaction, 'address');
|
||||
@@ -1624,7 +1691,7 @@ module.exports = class binance extends Exchange {
|
||||
tag = undefined;
|
||||
}
|
||||
}
|
||||
const txid = this.safeValue (transaction, 'txId');
|
||||
const txid = this.safeString (transaction, 'txId');
|
||||
const currencyId = this.safeString (transaction, 'asset');
|
||||
const code = this.safeCurrencyCode (currencyId, currency);
|
||||
let timestamp = undefined;
|
||||
@@ -1854,6 +1921,11 @@ module.exports = class binance extends Exchange {
|
||||
'timestamp': this.nonce (),
|
||||
'recvWindow': this.options['recvWindow'],
|
||||
}, params));
|
||||
} else if (path === 'batchOrders') {
|
||||
query = this.rawencode (this.extend ({
|
||||
'timestamp': this.nonce (),
|
||||
'recvWindow': this.options['recvWindow'],
|
||||
}, params));
|
||||
} else {
|
||||
query = this.urlencode (this.extend ({
|
||||
'timestamp': this.nonce (),
|
||||
|
||||
+3
-3
@@ -31,10 +31,10 @@ module.exports = class binanceus extends binance {
|
||||
},
|
||||
'fees': {
|
||||
'trading': {
|
||||
'tierBased': false,
|
||||
'tierBased': true,
|
||||
'percentage': true,
|
||||
'taker': 0.0, // 0.1% trading fee, zero fees for all trading pairs before November 1
|
||||
'maker': 0.0, // 0.1% trading fee, zero fees for all trading pairs before November 1
|
||||
'taker': 0.001, // 0.1% trading fee, zero fees for all trading pairs before November 1
|
||||
'maker': 0.001, // 0.1% trading fee, zero fees for all trading pairs before November 1
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
+67
-2
@@ -3,7 +3,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const Exchange = require ('./base/Exchange');
|
||||
const { InvalidNonce, InsufficientFunds, AuthenticationError, InvalidOrder, ExchangeError, OrderNotFound, AccountSuspended, BadSymbol, OrderImmediatelyFillable, RateLimitExceeded } = require ('./base/errors');
|
||||
const { InvalidNonce, InsufficientFunds, AuthenticationError, InvalidOrder, ExchangeError, OrderNotFound, AccountSuspended, BadSymbol, OrderImmediatelyFillable, RateLimitExceeded, OnMaintenance } = require ('./base/errors');
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -53,6 +53,7 @@ module.exports = class bitbay extends Exchange {
|
||||
'https://github.com/BitBayNet/API',
|
||||
'https://docs.bitbay.net/v1.0.1-en/reference',
|
||||
],
|
||||
'support': 'https://support.bitbay.net',
|
||||
'fees': 'https://bitbay.net/en/fees',
|
||||
},
|
||||
'api': {
|
||||
@@ -117,8 +118,60 @@ module.exports = class bitbay extends Exchange {
|
||||
},
|
||||
'fees': {
|
||||
'trading': {
|
||||
'maker': 0.0,
|
||||
'taker': 0.1 / 100,
|
||||
'percentage': true,
|
||||
'tierBased': false,
|
||||
},
|
||||
'fiat': {
|
||||
'maker': 0.30 / 100,
|
||||
'taker': 0.43 / 100,
|
||||
'percentage': true,
|
||||
'tierBased': true,
|
||||
'tiers': {
|
||||
'taker': [
|
||||
[ 0.0043, 0 ],
|
||||
[ 0.0042, 1250 ],
|
||||
[ 0.0041, 3750 ],
|
||||
[ 0.0040, 7500 ],
|
||||
[ 0.0039, 10000 ],
|
||||
[ 0.0038, 15000 ],
|
||||
[ 0.0037, 20000 ],
|
||||
[ 0.0036, 25000 ],
|
||||
[ 0.0035, 37500 ],
|
||||
[ 0.0034, 50000 ],
|
||||
[ 0.0033, 75000 ],
|
||||
[ 0.0032, 100000 ],
|
||||
[ 0.0031, 150000 ],
|
||||
[ 0.0030, 200000 ],
|
||||
[ 0.0029, 250000 ],
|
||||
[ 0.0028, 375000 ],
|
||||
[ 0.0027, 500000 ],
|
||||
[ 0.0026, 625000 ],
|
||||
[ 0.0025, 875000 ],
|
||||
],
|
||||
'maker': [
|
||||
[ 0.0030, 0 ],
|
||||
[ 0.0029, 1250 ],
|
||||
[ 0.0028, 3750 ],
|
||||
[ 0.0028, 7500 ],
|
||||
[ 0.0027, 10000 ],
|
||||
[ 0.0026, 15000 ],
|
||||
[ 0.0025, 20000 ],
|
||||
[ 0.0025, 25000 ],
|
||||
[ 0.0024, 37500 ],
|
||||
[ 0.0023, 50000 ],
|
||||
[ 0.0023, 75000 ],
|
||||
[ 0.0022, 100000 ],
|
||||
[ 0.0021, 150000 ],
|
||||
[ 0.0021, 200000 ],
|
||||
[ 0.0020, 250000 ],
|
||||
[ 0.0019, 375000 ],
|
||||
[ 0.0018, 500000 ],
|
||||
[ 0.0018, 625000 ],
|
||||
[ 0.0017, 875000 ],
|
||||
],
|
||||
},
|
||||
},
|
||||
'funding': {
|
||||
'withdraw': {
|
||||
@@ -135,6 +188,9 @@ module.exports = class bitbay extends Exchange {
|
||||
},
|
||||
},
|
||||
},
|
||||
'options': {
|
||||
'fiatCurrencies': [ 'EUR', 'USD', 'GBP', 'PLN' ],
|
||||
},
|
||||
'exceptions': {
|
||||
'400': ExchangeError, // At least one parameter wasn't set
|
||||
'401': InvalidOrder, // Invalid order type
|
||||
@@ -159,12 +215,14 @@ module.exports = class bitbay extends Exchange {
|
||||
'OFFER_NOT_FOUND': OrderNotFound,
|
||||
'OFFER_WOULD_HAVE_BEEN_PARTIALLY_FILLED': OrderImmediatelyFillable,
|
||||
'ACTION_LIMIT_EXCEEDED': RateLimitExceeded,
|
||||
'UNDER_MAINTENANCE': OnMaintenance,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async fetchMarkets (params = {}) {
|
||||
const response = await this.v1_01PublicGetTradingTicker (params);
|
||||
const fiatCurrencies = this.safeValue (this.options, 'fiatCurrencies', []);
|
||||
//
|
||||
// {
|
||||
// status: 'Ok',
|
||||
@@ -203,6 +261,12 @@ module.exports = class bitbay extends Exchange {
|
||||
'amount': this.safeInteger (first, 'scale'),
|
||||
'price': this.safeInteger (second, 'scale'),
|
||||
};
|
||||
let fees = this.safeValue (this.fees, 'trading', {});
|
||||
if (this.inArray (base, fiatCurrencies) || this.inArray (quote, fiatCurrencies)) {
|
||||
fees = this.safeValue (this.fees, 'fiat', {});
|
||||
}
|
||||
const maker = this.safeFloat (fees, 'maker');
|
||||
const taker = this.safeFloat (fees, 'taker');
|
||||
// todo: check that the limits have ben interpreted correctly
|
||||
// todo: parse the fees page
|
||||
result.push ({
|
||||
@@ -214,7 +278,8 @@ module.exports = class bitbay extends Exchange {
|
||||
'quoteId': quoteId,
|
||||
'precision': precision,
|
||||
'active': undefined,
|
||||
'fee': undefined,
|
||||
'maker': maker,
|
||||
'taker': taker,
|
||||
'limits': {
|
||||
'amount': {
|
||||
'min': this.safeFloat (first, 'minOffer'),
|
||||
|
||||
+6
-6
@@ -905,12 +905,12 @@ module.exports = class bitfinex extends Exchange {
|
||||
|
||||
parseOHLCV (ohlcv, market = undefined, timeframe = '1m', since = undefined, limit = undefined) {
|
||||
return [
|
||||
ohlcv[0],
|
||||
ohlcv[1],
|
||||
ohlcv[3],
|
||||
ohlcv[4],
|
||||
ohlcv[2],
|
||||
ohlcv[5],
|
||||
this.safeInteger (ohlcv, 0),
|
||||
this.safeFloat (ohlcv, 1),
|
||||
this.safeFloat (ohlcv, 3),
|
||||
this.safeFloat (ohlcv, 4),
|
||||
this.safeFloat (ohlcv, 2),
|
||||
this.safeFloat (ohlcv, 5),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -699,6 +699,7 @@ module.exports = class bitfinex2 extends bitfinex {
|
||||
'PARTIALLY FILLED': 'open',
|
||||
'EXECUTED': 'closed',
|
||||
'CANCELED': 'canceled',
|
||||
'CANCELED was: PARTIALLY FILLED': 'canceled',
|
||||
'INSUFFICIENT MARGIN': 'canceled',
|
||||
'INSUFFICIENT BALANCE (G1) was: PARTIALLY FILLED': 'canceled',
|
||||
'RSN_DUST': 'rejected',
|
||||
|
||||
+393
-44
@@ -3,7 +3,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const Exchange = require ('./base/Exchange');
|
||||
const { ExchangeError, ExchangeNotAvailable, AuthenticationError, BadRequest, PermissionDenied, InvalidAddress } = require ('./base/errors');
|
||||
const { ExchangeError, ExchangeNotAvailable, AuthenticationError, BadRequest, PermissionDenied, InvalidAddress, ArgumentsRequired, InvalidOrder } = require ('./base/errors');
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -16,7 +16,12 @@ module.exports = class bithumb extends Exchange {
|
||||
'rateLimit': 500,
|
||||
'has': {
|
||||
'CORS': true,
|
||||
'createOrder': true,
|
||||
'cancelOrder': true,
|
||||
'createMarketOrder': true,
|
||||
'fetchTickers': true,
|
||||
'fetchOpenOrders': true,
|
||||
'fetchOrder': true,
|
||||
'withdraw': true,
|
||||
},
|
||||
'urls': {
|
||||
@@ -48,8 +53,8 @@ module.exports = class bithumb extends Exchange {
|
||||
'info/ticker',
|
||||
'info/orders',
|
||||
'info/user_transactions',
|
||||
'trade/place',
|
||||
'info/order_detail',
|
||||
'trade/place',
|
||||
'trade/cancel',
|
||||
'trade/btc_withdrawal',
|
||||
'trade/krw_deposit',
|
||||
@@ -165,15 +170,53 @@ module.exports = class bithumb extends Exchange {
|
||||
'currency': market['base'],
|
||||
};
|
||||
if (limit !== undefined) {
|
||||
request['count'] = limit; // max = 50
|
||||
request['count'] = limit; // default 30, max 30
|
||||
}
|
||||
const response = await this.publicGetOrderbookCurrency (this.extend (request, params));
|
||||
const orderbook = this.safeValue (response, 'data');
|
||||
const timestamp = this.safeInteger (orderbook, 'timestamp');
|
||||
return this.parseOrderBook (orderbook, timestamp, 'bids', 'asks', 'price', 'quantity');
|
||||
//
|
||||
// {
|
||||
// "status":"0000",
|
||||
// "data":{
|
||||
// "timestamp":"1587621553942",
|
||||
// "payment_currency":"KRW",
|
||||
// "order_currency":"BTC",
|
||||
// "bids":[
|
||||
// {"price":"8652000","quantity":"0.0043"},
|
||||
// {"price":"8651000","quantity":"0.0049"},
|
||||
// {"price":"8650000","quantity":"8.4791"},
|
||||
// ],
|
||||
// "asks":[
|
||||
// {"price":"8654000","quantity":"0.119"},
|
||||
// {"price":"8655000","quantity":"0.254"},
|
||||
// {"price":"8658000","quantity":"0.119"},
|
||||
// ]
|
||||
// }
|
||||
// }
|
||||
//
|
||||
const data = this.safeValue (response, 'data', {});
|
||||
const timestamp = this.safeInteger (data, 'timestamp');
|
||||
return this.parseOrderBook (data, timestamp, 'bids', 'asks', 'price', 'quantity');
|
||||
}
|
||||
|
||||
parseTicker (ticker, market = undefined) {
|
||||
//
|
||||
// fetchTicker, fetchTickers
|
||||
//
|
||||
// {
|
||||
// "opening_price":"227100",
|
||||
// "closing_price":"228400",
|
||||
// "min_price":"222300",
|
||||
// "max_price":"230000",
|
||||
// "units_traded":"82618.56075337",
|
||||
// "acc_trade_value":"18767376138.6031",
|
||||
// "prev_closing_price":"227100",
|
||||
// "units_traded_24H":"151871.13484676",
|
||||
// "acc_trade_value_24H":"34247610416.8974",
|
||||
// "fluctate_24H":"8700",
|
||||
// "fluctate_rate_24H":"3.96",
|
||||
// "date":"1587710327264", // fetchTickers inject this
|
||||
// }
|
||||
//
|
||||
const timestamp = this.safeInteger (ticker, 'date');
|
||||
let symbol = undefined;
|
||||
if (market !== undefined) {
|
||||
@@ -224,9 +267,31 @@ module.exports = class bithumb extends Exchange {
|
||||
async fetchTickers (symbols = undefined, params = {}) {
|
||||
await this.loadMarkets ();
|
||||
const response = await this.publicGetTickerAll (params);
|
||||
//
|
||||
// {
|
||||
// "status":"0000",
|
||||
// "data":{
|
||||
// "BTC":{
|
||||
// "opening_price":"9045000",
|
||||
// "closing_price":"9132000",
|
||||
// "min_price":"8938000",
|
||||
// "max_price":"9168000",
|
||||
// "units_traded":"4619.79967497",
|
||||
// "acc_trade_value":"42021363832.5187",
|
||||
// "prev_closing_price":"9041000",
|
||||
// "units_traded_24H":"8793.5045804",
|
||||
// "acc_trade_value_24H":"78933458515.4962",
|
||||
// "fluctate_24H":"530000",
|
||||
// "fluctate_rate_24H":"6.16"
|
||||
// },
|
||||
// "date":"1587710878669"
|
||||
// }
|
||||
// }
|
||||
//
|
||||
const result = {};
|
||||
const timestamp = this.safeInteger (response['data'], 'date');
|
||||
const tickers = this.omit (response['data'], 'date');
|
||||
const data = this.safeValue (response, 'data', {});
|
||||
const timestamp = this.safeInteger (data, 'date');
|
||||
const tickers = this.omit (data, 'date');
|
||||
const ids = Object.keys (tickers);
|
||||
for (let i = 0; i < ids.length; i++) {
|
||||
const id = ids[i];
|
||||
@@ -253,19 +318,72 @@ module.exports = class bithumb extends Exchange {
|
||||
'currency': market['base'],
|
||||
};
|
||||
const response = await this.publicGetTickerCurrency (this.extend (request, params));
|
||||
return this.parseTicker (response['data'], market);
|
||||
//
|
||||
// {
|
||||
// "status":"0000",
|
||||
// "data":{
|
||||
// "opening_price":"227100",
|
||||
// "closing_price":"228400",
|
||||
// "min_price":"222300",
|
||||
// "max_price":"230000",
|
||||
// "units_traded":"82618.56075337",
|
||||
// "acc_trade_value":"18767376138.6031",
|
||||
// "prev_closing_price":"227100",
|
||||
// "units_traded_24H":"151871.13484676",
|
||||
// "acc_trade_value_24H":"34247610416.8974",
|
||||
// "fluctate_24H":"8700",
|
||||
// "fluctate_rate_24H":"3.96",
|
||||
// "date":"1587710327264"
|
||||
// }
|
||||
// }
|
||||
//
|
||||
const data = this.safeValue (response, 'data', {});
|
||||
return this.parseTicker (data, market);
|
||||
}
|
||||
|
||||
parseTrade (trade, market = undefined) {
|
||||
//
|
||||
// fetchTrades (public)
|
||||
//
|
||||
// {
|
||||
// "transaction_date":"2020-04-23 22:21:46",
|
||||
// "type":"ask",
|
||||
// "units_traded":"0.0125",
|
||||
// "price":"8667000",
|
||||
// "total":"108337"
|
||||
// }
|
||||
//
|
||||
// fetchOrder (private)
|
||||
//
|
||||
// {
|
||||
// "transaction_date": "1572497603902030",
|
||||
// "price": "8601000",
|
||||
// "units": "0.005",
|
||||
// "fee_currency": "KRW",
|
||||
// "fee": "107.51",
|
||||
// "total": "43005"
|
||||
// }
|
||||
//
|
||||
// a workaround for their bug in date format, hours are not 0-padded
|
||||
const parts = trade['transaction_date'].split (' ');
|
||||
const transaction_date = parts[0];
|
||||
let transaction_time = parts[1];
|
||||
if (transaction_time.length < 8) {
|
||||
transaction_time = '0' + transaction_time;
|
||||
let timestamp = undefined;
|
||||
const transactionDatetime = this.safeString (trade, 'transaction_date');
|
||||
if (transactionDatetime !== undefined) {
|
||||
const parts = transactionDatetime.split (' ');
|
||||
const numParts = parts.length;
|
||||
if (numParts > 1) {
|
||||
const transactionDate = parts[0];
|
||||
let transactionTime = parts[1];
|
||||
if (transactionTime.length < 8) {
|
||||
transactionTime = '0' + transactionTime;
|
||||
}
|
||||
timestamp = this.parse8601 (transactionDate + ' ' + transactionTime);
|
||||
} else {
|
||||
timestamp = this.safeIntegerProduct (trade, 'transaction_date', 0.001);
|
||||
}
|
||||
}
|
||||
if (timestamp !== undefined) {
|
||||
timestamp -= 9 * 3600000; // they report UTC + 9 hours, server in Korean timezone
|
||||
}
|
||||
let timestamp = this.parse8601 (transaction_date + ' ' + transaction_time);
|
||||
timestamp -= 9 * 3600000; // they report UTC + 9 hours (server in Korean timezone)
|
||||
const type = undefined;
|
||||
let side = this.safeString (trade, 'type');
|
||||
side = (side === 'ask') ? 'sell' : 'buy';
|
||||
@@ -276,12 +394,24 @@ module.exports = class bithumb extends Exchange {
|
||||
}
|
||||
const price = this.safeFloat (trade, 'price');
|
||||
const amount = this.safeFloat (trade, 'units_traded');
|
||||
let cost = undefined;
|
||||
if (amount !== undefined) {
|
||||
if (price !== undefined) {
|
||||
cost = price * amount;
|
||||
let cost = this.safeFloat (trade, 'total');
|
||||
if (cost === undefined) {
|
||||
if (amount !== undefined) {
|
||||
if (price !== undefined) {
|
||||
cost = price * amount;
|
||||
}
|
||||
}
|
||||
}
|
||||
let fee = undefined;
|
||||
const feeCost = this.safeFloat (trade, 'fee');
|
||||
if (feeCost !== undefined) {
|
||||
const feeCurrencyId = this.safeString (trade, 'fee_currency');
|
||||
const feeCurrencyCode = this.commonCurrencyCode (feeCurrencyId);
|
||||
fee = {
|
||||
'cost': feeCost,
|
||||
'currency': feeCurrencyCode,
|
||||
};
|
||||
}
|
||||
return {
|
||||
'id': id,
|
||||
'info': trade,
|
||||
@@ -295,7 +425,7 @@ module.exports = class bithumb extends Exchange {
|
||||
'price': price,
|
||||
'amount': amount,
|
||||
'cost': cost,
|
||||
'fee': undefined,
|
||||
'fee': fee,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -309,57 +439,276 @@ module.exports = class bithumb extends Exchange {
|
||||
request['count'] = limit; // default 20, max 100
|
||||
}
|
||||
const response = await this.publicGetTransactionHistoryCurrency (this.extend (request, params));
|
||||
return this.parseTrades (response['data'], market, since, limit);
|
||||
//
|
||||
// {
|
||||
// "status":"0000",
|
||||
// "data":[
|
||||
// {
|
||||
// "transaction_date":"2020-04-23 22:21:46",
|
||||
// "type":"ask",
|
||||
// "units_traded":"0.0125",
|
||||
// "price":"8667000",
|
||||
// "total":"108337"
|
||||
// },
|
||||
// ]
|
||||
// }
|
||||
//
|
||||
const data = this.safeValue (response, 'data', []);
|
||||
return this.parseTrades (data, market, since, limit);
|
||||
}
|
||||
|
||||
async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
|
||||
await this.loadMarkets ();
|
||||
const market = this.market (symbol);
|
||||
let request = undefined;
|
||||
let method = 'privatePostTrade';
|
||||
const request = {
|
||||
'order_currency': market['id'],
|
||||
'Payment_currency': market['quote'],
|
||||
'units': amount,
|
||||
};
|
||||
let method = 'privatePostTradePlace';
|
||||
if (type === 'limit') {
|
||||
request = {
|
||||
'order_currency': market['id'],
|
||||
'Payment_currency': market['quote'],
|
||||
'units': amount,
|
||||
'price': price,
|
||||
'type': (side === 'buy') ? 'bid' : 'ask',
|
||||
};
|
||||
method += 'Place';
|
||||
} else if (type === 'market') {
|
||||
request = {
|
||||
'currency': market['id'],
|
||||
'units': amount,
|
||||
};
|
||||
method += 'Market' + this.capitalize (side);
|
||||
request['price'] = price;
|
||||
request['type'] = (side === 'buy') ? 'bid' : 'ask';
|
||||
} else {
|
||||
method = 'privatePostTradeMarket' + this.capitalize (side);
|
||||
}
|
||||
const response = await this[method] (this.extend (request, params));
|
||||
const id = this.safeString (response, 'order_id');
|
||||
if (id === undefined) {
|
||||
throw new InvalidOrder (this.id + ' createOrder did not return an order id');
|
||||
}
|
||||
return {
|
||||
'info': response,
|
||||
'symbol': symbol,
|
||||
'type': type,
|
||||
'side': side,
|
||||
'id': id,
|
||||
};
|
||||
}
|
||||
|
||||
async fetchOrder (id, symbol = undefined, params = {}) {
|
||||
if (symbol === undefined) {
|
||||
throw new ArgumentsRequired (this.id + ' fetchOrder requires a symbol argument');
|
||||
}
|
||||
await this.loadMarkets ();
|
||||
const market = this.market (symbol);
|
||||
const request = {
|
||||
'order_id': id,
|
||||
'count': 1,
|
||||
'order_currency': market['base'],
|
||||
'payment_currency': market['quote'],
|
||||
};
|
||||
const response = await this.privatePostInfoOrderDetail (this.extend (request, params));
|
||||
//
|
||||
// {
|
||||
// "status": "0000",
|
||||
// "data": {
|
||||
// "transaction_date": "1572497603668315",
|
||||
// "type": "bid",
|
||||
// "order_status": "Completed",
|
||||
// "order_currency": "BTC",
|
||||
// "payment_currency": "KRW",
|
||||
// "order_price": "8601000",
|
||||
// "order_qty": "0.007",
|
||||
// "cancel_date": "",
|
||||
// "cancel_type": "",
|
||||
// "contract": [
|
||||
// {
|
||||
// "transaction_date": "1572497603902030",
|
||||
// "price": "8601000",
|
||||
// "units": "0.005",
|
||||
// "fee_currency": "KRW",
|
||||
// "fee": "107.51",
|
||||
// "total": "43005"
|
||||
// },
|
||||
// ]
|
||||
// }
|
||||
// }
|
||||
//
|
||||
const data = this.safeValue (response, 'data');
|
||||
return this.parseOrder (this.extend (data, { 'order_id': id }), market);
|
||||
}
|
||||
|
||||
parseOrderStatus (status) {
|
||||
const statuses = {
|
||||
'Pending': 'open',
|
||||
'Completed': 'closed',
|
||||
'Cancel': 'canceled',
|
||||
};
|
||||
return this.safeString (statuses, status, status);
|
||||
}
|
||||
|
||||
parseOrder (order, market = undefined) {
|
||||
//
|
||||
// fetchOrder
|
||||
//
|
||||
// {
|
||||
// "transaction_date": "1572497603668315",
|
||||
// "type": "bid",
|
||||
// "order_status": "Completed",
|
||||
// "order_currency": "BTC",
|
||||
// "payment_currency": "KRW",
|
||||
// "order_price": "8601000",
|
||||
// "order_qty": "0.007",
|
||||
// "cancel_date": "",
|
||||
// "cancel_type": "",
|
||||
// "contract": [
|
||||
// {
|
||||
// "transaction_date": "1572497603902030",
|
||||
// "price": "8601000",
|
||||
// "units": "0.005",
|
||||
// "fee_currency": "KRW",
|
||||
// "fee": "107.51",
|
||||
// "total": "43005"
|
||||
// },
|
||||
// ]
|
||||
// }
|
||||
//
|
||||
// fetchOpenOrders
|
||||
//
|
||||
// {
|
||||
// "order_currency": "BTC",
|
||||
// "payment_currency": "KRW",
|
||||
// "order_id": "C0101000007408440032",
|
||||
// "order_date": "1571728739360570",
|
||||
// "type": "bid",
|
||||
// "units": "5.0",
|
||||
// "units_remaining": "5.0",
|
||||
// "price": "501000",
|
||||
// }
|
||||
//
|
||||
const timestamp = this.safeIntegerProduct (order, 'order_date', 0.001);
|
||||
const sideProperty = this.safeValue2 (order, 'type', 'side');
|
||||
const side = (sideProperty === 'bid') ? 'buy' : 'sell';
|
||||
const status = this.parseOrderStatus (this.safeString (order, 'order_status'));
|
||||
let price = this.safeFloat2 (order, 'order_price', 'price');
|
||||
let type = 'limit';
|
||||
if (price === 0) {
|
||||
price = undefined;
|
||||
type = 'market';
|
||||
}
|
||||
const amount = this.safeFloat2 (order, 'order_qty', 'units');
|
||||
let remaining = this.safeFloat (order, 'units_remaining');
|
||||
if (remaining === undefined) {
|
||||
if (status === 'closed') {
|
||||
remaining = 0;
|
||||
} else {
|
||||
remaining = amount;
|
||||
}
|
||||
}
|
||||
let filled = undefined;
|
||||
if ((amount !== undefined) && (remaining !== undefined)) {
|
||||
filled = amount - remaining;
|
||||
}
|
||||
let symbol = undefined;
|
||||
const baseId = this.safeString (order, 'order_currency');
|
||||
const quoteId = this.safeString (order, 'payment_currency');
|
||||
const base = this.safeCurrencyCode (baseId);
|
||||
const quote = this.safeCurrencyCode (quoteId);
|
||||
if ((base !== undefined) && (quote !== undefined)) {
|
||||
symbol = base + '/' + quote;
|
||||
}
|
||||
if ((symbol === undefined) && (market !== undefined)) {
|
||||
symbol = market['symbol'];
|
||||
}
|
||||
const rawTrades = this.safeValue (order, 'contract');
|
||||
let trades = undefined;
|
||||
const id = this.safeString (order, 'order_id');
|
||||
if (rawTrades !== undefined) {
|
||||
trades = this.parseTrades (rawTrades, market, undefined, undefined, {
|
||||
'side': side,
|
||||
'symbol': symbol,
|
||||
'order': id,
|
||||
});
|
||||
}
|
||||
return {
|
||||
'info': order,
|
||||
'id': id,
|
||||
'timestamp': timestamp,
|
||||
'datetime': this.iso8601 (timestamp),
|
||||
'lastTradeTimestamp': undefined,
|
||||
'symbol': symbol,
|
||||
'type': type,
|
||||
'side': side,
|
||||
'price': price,
|
||||
'amount': amount,
|
||||
'cost': undefined,
|
||||
'average': undefined,
|
||||
'filled': filled,
|
||||
'remaining': remaining,
|
||||
'status': status,
|
||||
'fee': undefined,
|
||||
'trades': trades,
|
||||
};
|
||||
}
|
||||
|
||||
async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
||||
if (symbol === undefined) {
|
||||
throw new ArgumentsRequired (this.id + ' fetchOpenOrders requires a symbol argument');
|
||||
}
|
||||
await this.loadMarkets ();
|
||||
const market = this.market (symbol);
|
||||
if (limit === undefined) {
|
||||
limit = 100;
|
||||
}
|
||||
const request = {
|
||||
'count': limit,
|
||||
'order_currency': market['base'],
|
||||
'payment_currency': market['quote'],
|
||||
};
|
||||
if (since !== undefined) {
|
||||
request['after'] = since;
|
||||
}
|
||||
const response = await this.privatePostInfoOrders (this.extend (request, params));
|
||||
//
|
||||
// {
|
||||
// "status": "0000",
|
||||
// "data": [
|
||||
// {
|
||||
// "order_currency": "BTC",
|
||||
// "payment_currency": "KRW",
|
||||
// "order_id": "C0101000007408440032",
|
||||
// "order_date": "1571728739360570",
|
||||
// "type": "bid",
|
||||
// "units": "5.0",
|
||||
// "units_remaining": "5.0",
|
||||
// "price": "501000",
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
//
|
||||
const data = this.safeValue (response, 'data', []);
|
||||
return this.parseOrders (data, market, since, limit);
|
||||
}
|
||||
|
||||
async cancelOrder (id, symbol = undefined, params = {}) {
|
||||
const side_in_params = ('side' in params);
|
||||
if (!side_in_params) {
|
||||
throw new ExchangeError (this.id + ' cancelOrder requires a `side` parameter (sell or buy) and a `currency` parameter');
|
||||
throw new ArgumentsRequired (this.id + ' cancelOrder requires a `symbol` argument and a `side` parameter (sell or buy)');
|
||||
}
|
||||
const currency = this.safeString (params, 'currency');
|
||||
if (currency === undefined) {
|
||||
throw new ExchangeError (this.id + ' cancelOrder requires a `currency` parameter (a currency id)');
|
||||
if (symbol === undefined) {
|
||||
throw new ArgumentsRequired (this.id + ' cancelOrder requires a `symbol` argument and a `side` parameter (sell or buy)');
|
||||
}
|
||||
const market = this.market (symbol);
|
||||
const side = (params['side'] === 'buy') ? 'bid' : 'ask';
|
||||
params = this.omit (params, [ 'side', 'currency' ]);
|
||||
// https://github.com/ccxt/ccxt/issues/6771
|
||||
const request = {
|
||||
'order_id': id,
|
||||
'type': side,
|
||||
'currency': currency,
|
||||
'order_currency': market['base'],
|
||||
'payment_currency': market['quote'],
|
||||
};
|
||||
return await this.privatePostTradeCancel (this.extend (request, params));
|
||||
}
|
||||
|
||||
cancelUnifiedOrder (order, params = {}) {
|
||||
const request = {
|
||||
'side': order['side'],
|
||||
};
|
||||
return this.cancelOrder (order['id'], order['symbol'], this.extend (request, params));
|
||||
}
|
||||
|
||||
async withdraw (code, amount, address, tag = undefined, params = {}) {
|
||||
this.checkAddress (address);
|
||||
await this.loadMarkets ();
|
||||
@@ -372,7 +721,7 @@ module.exports = class bithumb extends Exchange {
|
||||
if (currency === 'XRP' || currency === 'XMR') {
|
||||
const destination = this.safeString (params, 'destination');
|
||||
if ((tag === undefined) && (destination === undefined)) {
|
||||
throw new ExchangeError (this.id + ' ' + code + ' withdraw() requires a tag argument or an extra destination param');
|
||||
throw new ArgumentsRequired (this.id + ' ' + code + ' withdraw() requires a tag argument or an extra destination param');
|
||||
} else if (tag !== undefined) {
|
||||
request['destination'] = tag;
|
||||
}
|
||||
|
||||
+2
@@ -35,6 +35,7 @@ module.exports = class bitmart extends Exchange {
|
||||
'fetchClosedOrders': true,
|
||||
'fetchCanceledOrders': true,
|
||||
'fetchOrder': true,
|
||||
'signIn': true,
|
||||
},
|
||||
'urls': {
|
||||
'logo': 'https://user-images.githubusercontent.com/1294454/61835713-a2662f80-ae85-11e9-9d00-6442919701fd.jpg',
|
||||
@@ -42,6 +43,7 @@ module.exports = class bitmart extends Exchange {
|
||||
'www': 'https://www.bitmart.com/',
|
||||
'doc': 'https://github.com/bitmartexchange/bitmart-official-api-docs',
|
||||
'referral': 'http://www.bitmart.com/?r=rQCFLh',
|
||||
'fees': 'https://www.bitmart.com/fee/en',
|
||||
},
|
||||
'requiredCredentials': {
|
||||
'apiKey': true,
|
||||
|
||||
+9
-1
@@ -1134,11 +1134,19 @@ module.exports = class bitstamp extends Exchange {
|
||||
body = this.urlencode (query);
|
||||
contentType = 'application/x-www-form-urlencoded';
|
||||
headers['Content-Type'] = contentType;
|
||||
} else {
|
||||
// sending an empty POST request will trigger
|
||||
// an API0020 error returned by the exchange
|
||||
// therefore for empty requests we send a dummy object
|
||||
// https://github.com/ccxt/ccxt/issues/6846
|
||||
body = this.urlencode ({ 'foo': 'bar' });
|
||||
contentType = 'application/x-www-form-urlencoded';
|
||||
headers['Content-Type'] = contentType;
|
||||
}
|
||||
}
|
||||
const authBody = body ? body : '';
|
||||
const auth = xAuth + method + url.replace ('https://', '') + contentType + xAuthNonce + xAuthTimestamp + xAuthVersion + authBody;
|
||||
const signature = this.encode (this.hmac (this.encode (auth), this.encode (this.secret)));
|
||||
const signature = this.hmac (this.encode (auth), this.encode (this.secret));
|
||||
headers['X-Auth-Signature'] = signature;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -650,7 +650,7 @@ module.exports = class bitz extends Exchange {
|
||||
}
|
||||
} else {
|
||||
if (since !== undefined) {
|
||||
throw new ExchangeError (this.id + ' fetchOHLCV requires a limit argument if the since argument is specified');
|
||||
throw new ArgumentsRequired (this.id + ' fetchOHLCV requires a limit argument if the since argument is specified');
|
||||
}
|
||||
}
|
||||
const response = await this.marketGetKline (this.extend (request, params));
|
||||
|
||||
+5
-2
@@ -73,6 +73,9 @@ module.exports = class bleutrade extends Exchange {
|
||||
],
|
||||
},
|
||||
'v3Private': {
|
||||
'get': [
|
||||
'statement',
|
||||
],
|
||||
'post': [
|
||||
'getbalance',
|
||||
'getbalances',
|
||||
@@ -189,8 +192,8 @@ module.exports = class bleutrade extends Exchange {
|
||||
// MarketCurrencyLong: 'Litecoin',
|
||||
// BaseCurrencyLong: 'Tether' }
|
||||
const id = this.safeString (market, 'MarketName');
|
||||
const baseId = this.safeString (market, 'MarketCurrency');
|
||||
const quoteId = this.safeString (market, 'BaseCurrency');
|
||||
const baseId = this.safeString (market, 'MarketAsset');
|
||||
const quoteId = this.safeString (market, 'BaseAsset');
|
||||
const base = this.safeCurrencyCode (baseId);
|
||||
const quote = this.safeCurrencyCode (quoteId);
|
||||
const symbol = base + '/' + quote;
|
||||
|
||||
+1
@@ -18,6 +18,7 @@ module.exports = class btctradeua extends Exchange {
|
||||
'CORS': false,
|
||||
'createMarketOrder': false,
|
||||
'fetchOpenOrders': true,
|
||||
'signIn': true,
|
||||
},
|
||||
'urls': {
|
||||
'referral': 'https://btc-trade.com.ua/registration/22689',
|
||||
|
||||
+3
-3
@@ -3,7 +3,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const Exchange = require ('./base/Exchange');
|
||||
const { AddressPending, AuthenticationError, ExchangeError, NotSupported, PermissionDenied } = require ('./base/errors');
|
||||
const { AddressPending, AuthenticationError, ExchangeError, NotSupported, PermissionDenied, ArgumentsRequired } = require ('./base/errors');
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -692,7 +692,7 @@ module.exports = class buda extends Exchange {
|
||||
async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
|
||||
await this.loadMarkets ();
|
||||
if (code === undefined) {
|
||||
throw new ExchangeError (this.id + ': fetchDeposits() requires a currency code argument');
|
||||
throw new ArgumentsRequired (this.id + ': fetchDeposits() requires a currency code argument');
|
||||
}
|
||||
const currency = this.currency (code);
|
||||
const request = {
|
||||
@@ -707,7 +707,7 @@ module.exports = class buda extends Exchange {
|
||||
async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
|
||||
await this.loadMarkets ();
|
||||
if (code === undefined) {
|
||||
throw new ExchangeError (this.id + ': fetchDeposits() requires a currency code argument');
|
||||
throw new ArgumentsRequired (this.id + ': fetchDeposits() requires a currency code argument');
|
||||
}
|
||||
const currency = this.currency (code);
|
||||
const request = {
|
||||
|
||||
+220
-57
@@ -4,7 +4,7 @@
|
||||
|
||||
const Exchange = require ('./base/Exchange');
|
||||
const { TICK_SIZE } = require ('./base/functions/number');
|
||||
const { AuthenticationError, ExchangeError, ArgumentsRequired, PermissionDenied, InvalidOrder, OrderNotFound, InsufficientFunds, BadRequest, RateLimitExceeded, InvalidNonce } = require ('./base/errors');
|
||||
const { AuthenticationError, ExchangeError, ArgumentsRequired, PermissionDenied, InvalidOrder, OrderNotFound, InsufficientFunds, BadRequest, RateLimitExceeded, InvalidNonce, NotSupported } = require ('./base/errors');
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -48,7 +48,7 @@ module.exports = class bybit extends Exchange {
|
||||
'30m': '30',
|
||||
'1h': '60',
|
||||
'2h': '120',
|
||||
'3h': '180',
|
||||
'4h': '240',
|
||||
'6h': '360',
|
||||
'12h': '720',
|
||||
'1d': 'D',
|
||||
@@ -63,6 +63,7 @@ module.exports = class bybit extends Exchange {
|
||||
'www': 'https://www.bybit.com/',
|
||||
'doc': [
|
||||
'https://bybit-exchange.github.io/docs/inverse/',
|
||||
'https://bybit-exchange.github.io/docs/linear/',
|
||||
'https://github.com/bybit-exchange',
|
||||
],
|
||||
'fees': 'https://help.bybit.com/hc/en-us/articles/360039261154',
|
||||
@@ -116,6 +117,41 @@ module.exports = class bybit extends Exchange {
|
||||
'position/trading-stop',
|
||||
],
|
||||
},
|
||||
'publicLinear': {
|
||||
'get': [
|
||||
'kline',
|
||||
'recent-trading-records',
|
||||
'funding/prev-funding-rate',
|
||||
'mark-price-kline',
|
||||
],
|
||||
},
|
||||
'privateLinear': {
|
||||
'get': [
|
||||
'order/list',
|
||||
'order/search',
|
||||
'stop-order/list',
|
||||
'stop-order/search',
|
||||
'position/list',
|
||||
'position/set-auto-add-margin',
|
||||
'position/set-leverage',
|
||||
'position/switch-isolated',
|
||||
'position/trading-stop',
|
||||
'position/add-margin',
|
||||
'trade/execution/list',
|
||||
'trade/closed-pnl/list',
|
||||
'risk-limit',
|
||||
'funding/prev-funding',
|
||||
'funding/predicted-funding',
|
||||
],
|
||||
'post': [
|
||||
'order/create',
|
||||
'order/cancel',
|
||||
'order/cancelAll',
|
||||
'stop-order/create',
|
||||
'stop-order/cancel',
|
||||
'stop-order/cancelAll',
|
||||
],
|
||||
},
|
||||
'position': {
|
||||
'post': [
|
||||
'change-position-margin',
|
||||
@@ -227,6 +263,9 @@ module.exports = class bybit extends Exchange {
|
||||
},
|
||||
'precisionMode': TICK_SIZE,
|
||||
'options': {
|
||||
'marketTypes': {
|
||||
'BTC/USDT': 'linear',
|
||||
},
|
||||
'code': 'BTC',
|
||||
'fetchBalance': {
|
||||
'code': 'BTC',
|
||||
@@ -309,6 +348,8 @@ module.exports = class bybit extends Exchange {
|
||||
// }
|
||||
//
|
||||
const markets = this.safeValue (response, 'result', []);
|
||||
const options = this.safeValue (this.options, 'fetchMarkets', {});
|
||||
const linearQuoteCurrencies = this.safeValue (options, 'linear', { 'USDT': true });
|
||||
const result = [];
|
||||
for (let i = 0; i < markets.length; i++) {
|
||||
const market = markets[i];
|
||||
@@ -317,6 +358,8 @@ module.exports = class bybit extends Exchange {
|
||||
const quoteId = this.safeString (market, 'quote_currency');
|
||||
const base = this.safeCurrencyCode (baseId);
|
||||
const quote = this.safeCurrencyCode (quoteId);
|
||||
const linear = (quote in linearQuoteCurrencies);
|
||||
const inverse = !linear;
|
||||
const symbol = base + '/' + quote;
|
||||
const lotSizeFilter = this.safeValue (market, 'lot_size_filter', {});
|
||||
const priceFilter = this.safeValue (market, 'price_filter', {});
|
||||
@@ -333,6 +376,12 @@ module.exports = class bybit extends Exchange {
|
||||
'precision': precision,
|
||||
'taker': this.safeFloat (market, 'taker_fee'),
|
||||
'maker': this.safeFloat (market, 'maker_fee'),
|
||||
'type': 'future',
|
||||
'spot': false,
|
||||
'future': true,
|
||||
'option': false,
|
||||
'linear': linear,
|
||||
'inverse': inverse,
|
||||
'limits': {
|
||||
'amount': {
|
||||
'min': this.safeFloat (lotSizeFilter, 'min_trading_qty'),
|
||||
@@ -347,10 +396,6 @@ module.exports = class bybit extends Exchange {
|
||||
'max': undefined,
|
||||
},
|
||||
},
|
||||
'type': 'future',
|
||||
'spot': false,
|
||||
'future': true,
|
||||
'option': false,
|
||||
'info': market,
|
||||
});
|
||||
}
|
||||
@@ -610,13 +655,25 @@ module.exports = class bybit extends Exchange {
|
||||
// turnover: '162.32773718999994'
|
||||
// },
|
||||
//
|
||||
// {
|
||||
// "id":143536,
|
||||
// "symbol":"BTCUSDT",
|
||||
// "period":"15",
|
||||
// "start_at":1587883500,
|
||||
// "volume":1.035,
|
||||
// "open":7540.5,
|
||||
// "high":7541,
|
||||
// "low":7540.5,
|
||||
// "close":7541
|
||||
// }
|
||||
//
|
||||
return [
|
||||
this.safeTimestamp (ohlcv, 'open_time'),
|
||||
this.safeTimestamp2 (ohlcv, 'open_time', 'start_at'),
|
||||
this.safeFloat (ohlcv, 'open'),
|
||||
this.safeFloat (ohlcv, 'high'),
|
||||
this.safeFloat (ohlcv, 'low'),
|
||||
this.safeFloat (ohlcv, 'close'),
|
||||
this.safeFloat (ohlcv, 'turnover'),
|
||||
this.safeFloat2 (ohlcv, 'turnover', 'volume'),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -641,7 +698,13 @@ module.exports = class bybit extends Exchange {
|
||||
if (limit !== undefined) {
|
||||
request['limit'] = limit; // max 200, default 200
|
||||
}
|
||||
const response = await this.publicGetKlineList (this.extend (request, params));
|
||||
const marketTypes = this.safeValue (this.options, 'marketTypes', {});
|
||||
const marketType = this.safeString (marketTypes, symbol);
|
||||
const method = (marketType === 'linear') ? 'publicLinearGetKline' : 'publicGetKlineList';
|
||||
const response = await this[method] (this.extend (request, params));
|
||||
//
|
||||
// inverse perpetual BTC/USD
|
||||
//
|
||||
// {
|
||||
// ret_code: 0,
|
||||
// ret_msg: 'OK',
|
||||
@@ -662,6 +725,30 @@ module.exports = class bybit extends Exchange {
|
||||
// ],
|
||||
// time_now: '1583953082.397330'
|
||||
// }
|
||||
//
|
||||
// linear perpetual BTC/USDT
|
||||
//
|
||||
// {
|
||||
// "ret_code":0,
|
||||
// "ret_msg":"OK",
|
||||
// "ext_code":"",
|
||||
// "ext_info":"",
|
||||
// "result":[
|
||||
// {
|
||||
// "id":143536,
|
||||
// "symbol":"BTCUSDT",
|
||||
// "period":"15",
|
||||
// "start_at":1587883500,
|
||||
// "volume":1.035,
|
||||
// "open":7540.5,
|
||||
// "high":7541,
|
||||
// "low":7540.5,
|
||||
// "close":7541
|
||||
// }
|
||||
// ],
|
||||
// "time_now":"1587884120.168077"
|
||||
// }
|
||||
//
|
||||
const result = this.safeValue (response, 'result', {});
|
||||
return this.parseOHLCVs (result, market, timeframe, since, limit);
|
||||
}
|
||||
@@ -688,6 +775,8 @@ module.exports = class bybit extends Exchange {
|
||||
// "exec_id": "256e5ef8-abfe-5772-971b-f944e15e0d68",
|
||||
// "exec_price": "8178.5",
|
||||
// "exec_qty": 1,
|
||||
// // the docs say the exec_time field is "abandoned" now
|
||||
// // the user should use "trade_time_ms"
|
||||
// "exec_time": "1571676941.70682",
|
||||
// "exec_type": "Trade", //Exec Type Enum
|
||||
// "exec_value": "0.00012227",
|
||||
@@ -702,30 +791,35 @@ module.exports = class bybit extends Exchange {
|
||||
// "order_type": "Market", //Order Type Enum
|
||||
// "side": "Buy", //Side Enum
|
||||
// "symbol": "BTCUSD", //Symbol Enum
|
||||
// "user_id": 1
|
||||
// "user_id": 1,
|
||||
// "trade_time_ms": 1577480599000
|
||||
// }
|
||||
//
|
||||
const id = this.safeString2 (trade, 'id', 'exec_id');
|
||||
let symbol = undefined;
|
||||
let base = undefined;
|
||||
const marketId = this.safeString (trade, 'symbol');
|
||||
let amount = this.safeFloat2 (trade, 'qty', 'exec_qty');
|
||||
let cost = this.safeFloat (trade, 'exec_value');
|
||||
const price = this.safeFloat2 (trade, 'price', 'exec_price');
|
||||
if (marketId in this.markets_by_id) {
|
||||
market = this.markets_by_id[marketId];
|
||||
symbol = market['symbol'];
|
||||
base = market['base'];
|
||||
}
|
||||
if ((symbol === undefined) && (market !== undefined)) {
|
||||
symbol = market['symbol'];
|
||||
base = market['base'];
|
||||
if (market !== undefined) {
|
||||
if (symbol === undefined) {
|
||||
symbol = market['symbol'];
|
||||
base = market['base'];
|
||||
}
|
||||
// if private trade
|
||||
if ('exec_fee' in trade) {
|
||||
if (market['inverse']) {
|
||||
amount = this.safeFloat (trade, 'exec_value');
|
||||
cost = this.safeFloat (trade, 'exec_qty');
|
||||
}
|
||||
}
|
||||
}
|
||||
let timestamp = this.parse8601 (this.safeString (trade, 'time'));
|
||||
if (timestamp === undefined) {
|
||||
timestamp = this.safeTimestamp (trade, 'exec_time');
|
||||
}
|
||||
const side = this.safeStringLower (trade, 'side');
|
||||
const price = this.safeFloat2 (trade, 'price', 'exec_price');
|
||||
const amount = this.safeFloat2 (trade, 'qty', 'exec_qty');
|
||||
let cost = this.safeFloat (trade, 'exec_value');
|
||||
if (cost === undefined) {
|
||||
if (amount !== undefined) {
|
||||
if (price !== undefined) {
|
||||
@@ -733,6 +827,11 @@ module.exports = class bybit extends Exchange {
|
||||
}
|
||||
}
|
||||
}
|
||||
let timestamp = this.parse8601 (this.safeString (trade, 'time'));
|
||||
if (timestamp === undefined) {
|
||||
timestamp = this.safeInteger (trade, 'trade_time_ms');
|
||||
}
|
||||
const side = this.safeStringLower (trade, 'side');
|
||||
const lastLiquidityInd = this.safeString (trade, 'last_liquidity_ind');
|
||||
const takerOrMaker = (lastLiquidityInd === 'AddedLiquidity') ? 'maker' : 'taker';
|
||||
const feeCost = this.safeFloat (trade, 'exec_fee');
|
||||
@@ -771,7 +870,10 @@ module.exports = class bybit extends Exchange {
|
||||
if (limit !== undefined) {
|
||||
request['count'] = limit; // default 500, max 1000
|
||||
}
|
||||
const response = await this.publicGetTradingRecords (this.extend (request, params));
|
||||
const marketTypes = this.safeValue (this.options, 'marketTypes', {});
|
||||
const marketType = this.safeString (marketTypes, symbol);
|
||||
const method = (marketType === 'linear') ? 'publicLinearGetRecentTradingRecords' : 'publicGetTradingRecords';
|
||||
const response = await this[method] (this.extend (request, params));
|
||||
//
|
||||
// {
|
||||
// ret_code: 0,
|
||||
@@ -885,8 +987,8 @@ module.exports = class bybit extends Exchange {
|
||||
// "last_exec_time": 0,
|
||||
// "last_exec_price": 0,
|
||||
// "leaves_qty": 1,
|
||||
// "cum_exec_qty": 0,
|
||||
// "cum_exec_value": 0,
|
||||
// "cum_exec_qty": 0, // in contracts, where 1 contract = 1 quote currency unit (USD for inverse contracts)
|
||||
// "cum_exec_value": 0, // in contract's underlying currency (BTC for inverse contracts)
|
||||
// "cum_exec_fee": 0,
|
||||
// "reject_reason": "",
|
||||
// "order_link_id": "",
|
||||
@@ -894,18 +996,69 @@ module.exports = class bybit extends Exchange {
|
||||
// "updated_at": "2019-11-30T11:03:43.455Z"
|
||||
// }
|
||||
//
|
||||
// fetchOrder
|
||||
//
|
||||
// {
|
||||
// "user_id" : 599946,
|
||||
// "symbol" : "BTCUSD",
|
||||
// "side" : "Buy",
|
||||
// "order_type" : "Limit",
|
||||
// "price" : "7948",
|
||||
// "qty" : 10,
|
||||
// "time_in_force" : "GoodTillCancel",
|
||||
// "order_status" : "Filled",
|
||||
// "ext_fields" : {
|
||||
// "o_req_num" : -1600687220498,
|
||||
// "xreq_type" : "x_create"
|
||||
// },
|
||||
// "last_exec_time" : "1588150113.968422",
|
||||
// "last_exec_price" : "7948",
|
||||
// "leaves_qty" : 0,
|
||||
// "leaves_value" : "0",
|
||||
// "cum_exec_qty" : 10,
|
||||
// "cum_exec_value" : "0.00125817",
|
||||
// "cum_exec_fee" : "-0.00000031",
|
||||
// "reject_reason" : "",
|
||||
// "cancel_type" : "",
|
||||
// "order_link_id" : "",
|
||||
// "created_at" : "2020-04-29T08:45:24.399146Z",
|
||||
// "updated_at" : "2020-04-29T08:48:33.968422Z",
|
||||
// "order_id" : "dd2504b9-0157-406a-99e1-efa522373944"
|
||||
// }
|
||||
//
|
||||
const marketId = this.safeString (order, 'symbol');
|
||||
let symbol = undefined;
|
||||
let base = undefined;
|
||||
if (marketId in this.markets_by_id) {
|
||||
market = this.markets_by_id[marketId];
|
||||
}
|
||||
const timestamp = this.parse8601 (this.safeString (order, 'created_at'));
|
||||
const id = this.safeString (order, 'order_id');
|
||||
const price = this.safeFloat (order, 'price');
|
||||
const average = this.safeFloat (order, 'average_price');
|
||||
const amount = this.safeFloat (order, 'qty');
|
||||
let filled = this.safeFloat (order, 'cum_exec_qty');
|
||||
let remaining = this.safeFloat (order, 'leaves_qty');
|
||||
let amount = undefined;
|
||||
let cost = undefined;
|
||||
let filled = undefined;
|
||||
let remaining = undefined;
|
||||
if (market !== undefined) {
|
||||
symbol = market['symbol'];
|
||||
base = market['base'];
|
||||
if (market['inverse']) {
|
||||
cost = this.safeFloat (order, 'cum_exec_qty');
|
||||
filled = this.safeFloat (order, 'cum_exec_value');
|
||||
remaining = this.safeFloat (order, 'leaves_value');
|
||||
amount = this.sum (filled, remaining);
|
||||
} else {
|
||||
amount = this.safeFloat (order, 'qty');
|
||||
cost = this.safeFloat (order, 'cum_exec_value');
|
||||
filled = this.safeFloat (order, 'cum_exec_qty');
|
||||
remaining = this.safeFloat (order, 'leaves_qty');
|
||||
}
|
||||
}
|
||||
let lastTradeTimestamp = this.safeTimestamp (order, 'last_exec_time');
|
||||
if (lastTradeTimestamp === 0) {
|
||||
lastTradeTimestamp = undefined;
|
||||
}
|
||||
let cost = this.safeFloat (order, 'cum_exec_value');
|
||||
if ((filled === undefined) && (amount !== undefined) && (remaining !== undefined)) {
|
||||
filled = amount - remaining;
|
||||
}
|
||||
@@ -920,22 +1073,6 @@ module.exports = class bybit extends Exchange {
|
||||
}
|
||||
}
|
||||
const status = this.parseOrderStatus (this.safeString (order, 'order_status'));
|
||||
const marketId = this.safeString (order, 'symbol');
|
||||
let symbol = undefined;
|
||||
let base = undefined;
|
||||
if (marketId in this.markets_by_id) {
|
||||
market = this.markets_by_id[marketId];
|
||||
symbol = market['symbol'];
|
||||
base = market['base'];
|
||||
}
|
||||
if (market !== undefined) {
|
||||
if (symbol === undefined) {
|
||||
symbol = market['symbol'];
|
||||
}
|
||||
if (base === undefined) {
|
||||
base = market['base'];
|
||||
}
|
||||
}
|
||||
const side = this.safeStringLower (order, 'side');
|
||||
let feeCost = this.safeFloat (order, 'cum_exec_fee');
|
||||
let fee = undefined;
|
||||
@@ -987,7 +1124,9 @@ module.exports = class bybit extends Exchange {
|
||||
// conditional orders ---------------------------------------------
|
||||
// 'stop_order_id': id, // one of stop_order_id or order_link_id is required for conditional orders
|
||||
};
|
||||
let method = 'privateGetOrder';
|
||||
const marketTypes = this.safeValue (this.options, 'marketTypes', {});
|
||||
const marketType = this.safeString (marketTypes, symbol);
|
||||
let method = (marketType === 'linear') ? 'privateLinearGetOrderSearch' : 'privateGetOrder';
|
||||
const stopOrderId = this.safeString (params, 'stop_order_id');
|
||||
if (stopOrderId === undefined) {
|
||||
const orderLinkId = this.safeString (params, 'order_link_id');
|
||||
@@ -995,7 +1134,7 @@ module.exports = class bybit extends Exchange {
|
||||
request['order_id'] = id;
|
||||
}
|
||||
} else {
|
||||
method = 'privateGetStopOrder';
|
||||
method = (marketType === 'linear') ? 'privateLinearGetStopOrderSearch' : 'privateGetStopOrder';
|
||||
}
|
||||
const response = await this[method] (this.extend (request, params));
|
||||
//
|
||||
@@ -1107,12 +1246,14 @@ module.exports = class bybit extends Exchange {
|
||||
}
|
||||
const stopPx = this.safeValue (params, 'stop_px');
|
||||
const basePrice = this.safeValue (params, 'base_price');
|
||||
let method = 'privatePostOrderCreate';
|
||||
const marketTypes = this.safeValue (this.options, 'marketTypes', {});
|
||||
const marketType = this.safeString (marketTypes, symbol);
|
||||
let method = (marketType === 'linear') ? 'privateLinearPostOrderCreate' : 'privatePostOrderCreate';
|
||||
if (stopPx !== undefined) {
|
||||
if (basePrice === undefined) {
|
||||
throw new ArgumentsRequired (this.id + ' createOrder requires both the stop_px and base_price params for a conditional ' + type + ' order');
|
||||
} else {
|
||||
method = 'openapiPostStopOrderCreate';
|
||||
method = (marketType === 'linear') ? 'privateLinearPostStopOrderCreate' : 'openapiPostStopOrderCreate';
|
||||
request['stop_px'] = this.priceToPrecision (symbol, stopPx);
|
||||
request['base_price'] = this.priceToPrecision (symbol, basePrice);
|
||||
params = this.omit (params, [ 'stop_px', 'base_price' ]);
|
||||
@@ -1206,6 +1347,11 @@ module.exports = class bybit extends Exchange {
|
||||
if (symbol === undefined) {
|
||||
throw new ArgumentsRequired (this.id + ' editOrder requires an symbol argument');
|
||||
}
|
||||
const marketTypes = this.safeValue (this.options, 'marketTypes', {});
|
||||
const marketType = this.safeString (marketTypes, symbol);
|
||||
if (marketType === 'linear') {
|
||||
throw new NotSupported (this.id + ' does not support editOrder for ' + marketType + ' ' + symbol + ' market type');
|
||||
}
|
||||
await this.loadMarkets ();
|
||||
const market = this.market (symbol);
|
||||
const request = {
|
||||
@@ -1283,7 +1429,9 @@ module.exports = class bybit extends Exchange {
|
||||
// conditional orders ---------------------------------------------
|
||||
// 'stop_order_id': id, // one of stop_order_id or order_link_id is required for conditional orders
|
||||
};
|
||||
let method = 'privatePostOrderCancel';
|
||||
const marketTypes = this.safeValue (this.options, 'marketTypes', {});
|
||||
const marketType = this.safeValue (marketTypes, symbol);
|
||||
let method = (marketType === 'linear') ? 'privateLinearPostOrderCancel' : 'privatePostOrderCancel';
|
||||
const stopOrderId = this.safeString (params, 'stop_order_id');
|
||||
if (stopOrderId === undefined) {
|
||||
const orderLinkId = this.safeString (params, 'order_link_id');
|
||||
@@ -1291,7 +1439,7 @@ module.exports = class bybit extends Exchange {
|
||||
request['order_id'] = id;
|
||||
}
|
||||
} else {
|
||||
method = 'openapiPostStopOrderCancel';
|
||||
method = (marketType === 'linear') ? 'privateLinearPostStopOrderCancel' : 'openapiPostStopOrderCancel';
|
||||
}
|
||||
const response = await this[method] (this.extend (request, params));
|
||||
const result = this.safeValue (response, 'result', {});
|
||||
@@ -1308,7 +1456,10 @@ module.exports = class bybit extends Exchange {
|
||||
'symbol': market['id'],
|
||||
};
|
||||
const options = this.safeValue (this.options, 'cancelAllOrders');
|
||||
const method = this.safeString (options, 'method', 'privatePostOrderCancelAll');
|
||||
const marketTypes = this.safeValue (this.options, 'marketTypes', {});
|
||||
const marketType = this.safeString (marketTypes, symbol);
|
||||
const defaultMethod = (marketType === 'linear') ? 'privateLinearPostOrderCancelAll' : 'privatePostOrderCancelAll';
|
||||
const method = this.safeString (options, 'method', defaultMethod);
|
||||
const response = await this[method] (this.extend (request, params));
|
||||
const result = this.safeValue (response, 'result', []);
|
||||
return this.parseOrders (result, market);
|
||||
@@ -1337,7 +1488,9 @@ module.exports = class bybit extends Exchange {
|
||||
request['limit'] = limit;
|
||||
}
|
||||
const options = this.safeValue (this.options, 'fetchOrders', {});
|
||||
let defaultMethod = 'openapiGetOrderList';
|
||||
const marketTypes = this.safeValue (this.options, 'marketTypes', {});
|
||||
const marketType = this.safeString (marketTypes, symbol);
|
||||
let defaultMethod = (marketType === 'linear') ? 'privateLinearGetOrderList' : 'openapiGetOrderList';
|
||||
let query = params;
|
||||
if (('stop_order_id' in params) || ('stop_order_status' in params)) {
|
||||
let stopOrderStatus = this.safeValue (params, 'stopOrderStatus');
|
||||
@@ -1348,7 +1501,7 @@ module.exports = class bybit extends Exchange {
|
||||
request['stop_order_status'] = stopOrderStatus;
|
||||
query = this.omit (params, 'stop_order_status');
|
||||
}
|
||||
defaultMethod = 'openapiGetStopOrderList';
|
||||
defaultMethod = (marketType === 'linear') ? 'privateLinearGetStopOrderList' : 'openapiGetStopOrderList';
|
||||
}
|
||||
const method = this.safeString (options, 'method', defaultMethod);
|
||||
const response = await this[method] (this.extend (request, query));
|
||||
@@ -1524,12 +1677,15 @@ module.exports = class bybit extends Exchange {
|
||||
request['symbol'] = market['id'];
|
||||
}
|
||||
if (since !== undefined) {
|
||||
request['start_time'] = parseInt (since / 1000);
|
||||
request['start_time'] = since;
|
||||
}
|
||||
if (limit !== undefined) {
|
||||
request['limit'] = limit; // default 20, max 50
|
||||
}
|
||||
const response = await this.privateGetExecutionList (this.extend (request, params));
|
||||
const marketTypes = this.safeValue (this.options, 'marketTypes', {});
|
||||
const marketType = this.safeString (marketTypes, symbol);
|
||||
const method = (marketType === 'linear') ? 'privateLinearGetTradeExecutionList' : 'privateGetExecutionList';
|
||||
const response = await this[method] (this.extend (request, params));
|
||||
//
|
||||
// {
|
||||
// "ret_code": 0,
|
||||
@@ -1864,6 +2020,11 @@ module.exports = class bybit extends Exchange {
|
||||
if (Object.keys (params).length) {
|
||||
request += '?' + this.rawencode (params);
|
||||
}
|
||||
} else if (api === 'publicLinear') {
|
||||
request = '/public/linear/' + request;
|
||||
if (Object.keys (params).length) {
|
||||
request += '?' + this.rawencode (params);
|
||||
}
|
||||
} else {
|
||||
this.checkRequiredCredentials ();
|
||||
if (api === 'openapi') {
|
||||
@@ -1871,14 +2032,16 @@ module.exports = class bybit extends Exchange {
|
||||
} else if (api === 'private') {
|
||||
// private v2
|
||||
request = '/' + this.version + '/' + api + '/' + request;
|
||||
} else if (api === 'privateLinear') {
|
||||
request = '/private/linear/' + request;
|
||||
} else {
|
||||
// position, user
|
||||
request += '/' + api + '/' + request;
|
||||
request = '/' + api + '/' + request;
|
||||
}
|
||||
const timestamp = this.nonce ();
|
||||
const query = this.extend (params, {
|
||||
'api_key': this.apiKey,
|
||||
'recvWindow': this.options['recvWindow'],
|
||||
'recv_window': this.options['recvWindow'],
|
||||
'timestamp': timestamp,
|
||||
});
|
||||
const auth = this.rawencode (this.keysort (query));
|
||||
|
||||
+11
-5
@@ -47,9 +47,15 @@ module.exports = class bytetrade extends Exchange {
|
||||
'1M': '1M',
|
||||
},
|
||||
'urls': {
|
||||
'test': 'https://api-v2-test.byte-trade.com',
|
||||
'test': {
|
||||
'market': 'https://api-v2-test.byte-trade.com',
|
||||
'public': 'https://api-v2-test.byte-trade.com',
|
||||
},
|
||||
'logo': 'https://user-images.githubusercontent.com/1294454/67288762-2f04a600-f4e6-11e9-9fd6-c60641919491.jpg',
|
||||
'api': 'https://api-v2.byte-trade.com',
|
||||
'api': {
|
||||
'market': 'https://api-v2.bytetrade.com',
|
||||
'public': 'https://api-v2.bytetrade.com',
|
||||
},
|
||||
'www': 'https://www.byte-trade.com',
|
||||
'doc': 'https://github.com/Bytetrade/bytetrade-official-api-docs/wiki',
|
||||
},
|
||||
@@ -1222,7 +1228,7 @@ module.exports = class bytetrade extends Exchange {
|
||||
this.numberToLE (address.length, 1),
|
||||
this.stringToBinary (this.encode (address)),
|
||||
this.numberToLE (parseInt (coinId), 4),
|
||||
this.numberToLE (Math.floor (parseInt (parseFloat (this.integerDivide (amountChain, eightBytes)))), 8),
|
||||
this.numberToLE (this.integerDivide (amountChain, eightBytes), 8),
|
||||
this.numberToLE (this.integerModulo (amountChain, eightBytes), 8),
|
||||
this.numberToLE (1, 1),
|
||||
this.numberToLE (this.integerDivide (assetFee, eightBytes), 8),
|
||||
@@ -1255,7 +1261,7 @@ module.exports = class bytetrade extends Exchange {
|
||||
this.numberToLE (middleAddress.length, 1),
|
||||
this.stringToBinary (this.encode (middleAddress)),
|
||||
this.numberToLE (parseInt (coinId), 4),
|
||||
this.numberToLE (Math.floor (parseInt (parseFloat (this.integerDivide (amountChain, eightBytes)))), 8),
|
||||
this.numberToLE (this.integerDivide (amountChain, eightBytes), 8),
|
||||
this.numberToLE (this.integerModulo (amountChain, eightBytes), 8),
|
||||
this.numberToLE (0, 1),
|
||||
this.numberToLE (1, 1),
|
||||
@@ -1358,7 +1364,7 @@ module.exports = class bytetrade extends Exchange {
|
||||
}
|
||||
|
||||
sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
|
||||
let url = this.urls['api'];
|
||||
let url = this.urls['api'][api];
|
||||
url += '/' + path;
|
||||
if (Object.keys (params).length) {
|
||||
url += '?' + this.urlencode (params);
|
||||
|
||||
+37
-1
@@ -564,9 +564,45 @@ module.exports = class cex extends Exchange {
|
||||
request['order_type'] = type;
|
||||
}
|
||||
const response = await this.privatePostPlaceOrderPair (this.extend (request, params));
|
||||
//
|
||||
// {
|
||||
// "id": "12978363524",
|
||||
// "time": 1586610022259,
|
||||
// "type": "buy",
|
||||
// "price": "0.033934",
|
||||
// "amount": "0.10722802",
|
||||
// "pending": "0.10722802",
|
||||
// "complete": false
|
||||
// }
|
||||
//
|
||||
const placedAmount = this.safeFloat (response, 'amount');
|
||||
const remaining = this.safeFloat (response, 'pending');
|
||||
const timestamp = this.safeValue (response, 'time');
|
||||
const complete = this.safeValue (response, 'complete');
|
||||
const status = complete ? 'closed' : 'open';
|
||||
let filled = undefined;
|
||||
if ((placedAmount !== undefined) && (remaining !== undefined)) {
|
||||
filled = Math.max (placedAmount - remaining, 0);
|
||||
}
|
||||
return {
|
||||
'id': this.safeString (response, 'id'),
|
||||
'info': response,
|
||||
'id': response['id'],
|
||||
'clientOrderId': undefined,
|
||||
'timestamp': timestamp,
|
||||
'datetime': this.iso8601 (timestamp),
|
||||
'lastTradeTimestamp': undefined,
|
||||
'type': type,
|
||||
'side': this.safeString (response, 'type'),
|
||||
'symbol': symbol,
|
||||
'status': status,
|
||||
'price': this.safeFloat (response, 'price'),
|
||||
'amount': placedAmount,
|
||||
'cost': undefined,
|
||||
'average': undefined,
|
||||
'remaining': remaining,
|
||||
'filled': filled,
|
||||
'fee': undefined,
|
||||
'trades': undefined,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+6
-2
@@ -561,6 +561,7 @@ module.exports = class coinmate extends Exchange {
|
||||
const statuses = {
|
||||
'FILLED': 'closed',
|
||||
'CANCELLED': 'canceled',
|
||||
'PARTIALLY_FILLED': 'open',
|
||||
'OPEN': 'open',
|
||||
};
|
||||
return this.safeString (statuses, status, status);
|
||||
@@ -623,12 +624,15 @@ module.exports = class coinmate extends Exchange {
|
||||
const price = this.safeFloat (order, 'price');
|
||||
const amount = this.safeFloat2 (order, 'originalAmount', 'amount');
|
||||
const remaining = this.safeFloat (order, 'remainingAmount', amount);
|
||||
const status = this.parseOrderStatus (this.safeString (order, 'status'));
|
||||
let status = this.parseOrderStatus (this.safeString (order, 'status'));
|
||||
const type = this.parseOrderType (this.safeString (order, 'orderTradeType'));
|
||||
let filled = undefined;
|
||||
let cost = undefined;
|
||||
if ((amount !== undefined) && (remaining !== undefined)) {
|
||||
filled = amount - remaining;
|
||||
filled = Math.min (amount - remaining, 0);
|
||||
if (remaining === 0) {
|
||||
status = 'closed';
|
||||
}
|
||||
if (price !== undefined) {
|
||||
cost = filled * price;
|
||||
}
|
||||
|
||||
-1
@@ -129,7 +129,6 @@ module.exports = class crex24 extends Exchange {
|
||||
'fetchClosedOrdersMethod': 'tradingGetOrderHistory', // or 'tradingGetActiveOrders'
|
||||
'fetchTickersMethod': 'publicGetTicker24hr',
|
||||
'defaultTimeInForce': 'GTC', // 'GTC' = Good To Cancel (default), 'IOC' = Immediate Or Cancel
|
||||
'defaultLimitOrderType': 'limit', // or 'limit_maker'
|
||||
'hasAlreadyAuthenticatedSuccessfully': false,
|
||||
'warnOnFetchOpenOrdersWithoutSymbol': true,
|
||||
'parseOrderToPrecision': false, // force amounts and costs in parseOrder to precision
|
||||
|
||||
+4
-2
@@ -525,11 +525,13 @@ module.exports = class deribit extends Exchange {
|
||||
'info': response,
|
||||
};
|
||||
const balance = this.safeValue (response, 'result', {});
|
||||
const currencyId = this.safeString (balance, 'currency');
|
||||
const currencyCode = this.safeCurrencyCode (currencyId);
|
||||
const account = this.account ();
|
||||
account['free'] = this.safeFloat (balance, 'availableFunds');
|
||||
account['used'] = this.safeFloat (balance, 'maintenanceMargin');
|
||||
account['total'] = this.safeFloat (balance, 'equity');
|
||||
result[code] = account;
|
||||
result[currencyCode] = account;
|
||||
return this.parseBalance (result);
|
||||
}
|
||||
|
||||
@@ -883,7 +885,7 @@ module.exports = class deribit extends Exchange {
|
||||
// M = maker, T = taker, MT = both
|
||||
takerOrMaker = (liquidity === 'M') ? 'maker' : 'taker';
|
||||
}
|
||||
const feeCost = this.safeFloat (trade, 'feeCost');
|
||||
const feeCost = this.safeFloat (trade, 'fee');
|
||||
let fee = undefined;
|
||||
if (feeCost !== undefined) {
|
||||
const feeCurrencyId = this.safeString (trade, 'fee_currency');
|
||||
|
||||
+363
-152
@@ -3,7 +3,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const Exchange = require ('./base/Exchange');
|
||||
const { ArgumentsRequired, ExchangeError, OrderNotFound, AuthenticationError, InsufficientFunds, InvalidOrder, InvalidNonce, NotSupported, OnMaintenance, RateLimitExceeded } = require ('./base/errors');
|
||||
const { ArgumentsRequired, ExchangeError, OrderNotFound, AuthenticationError, InsufficientFunds, InvalidOrder, InvalidNonce, NotSupported, OnMaintenance, RateLimitExceeded, BadRequest, PermissionDenied } = require ('./base/errors');
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -14,7 +14,7 @@ module.exports = class exmo extends Exchange {
|
||||
'name': 'EXMO',
|
||||
'countries': [ 'ES', 'RU' ], // Spain, Russia
|
||||
'rateLimit': 350, // once every 350 ms ≈ 180 requests per minute ≈ 3 requests per second
|
||||
'version': 'v1',
|
||||
'version': 'v1.1',
|
||||
'has': {
|
||||
'CORS': false,
|
||||
'fetchClosedOrders': 'emulated',
|
||||
@@ -32,6 +32,21 @@ module.exports = class exmo extends Exchange {
|
||||
'fetchFundingFees': true,
|
||||
'fetchCurrencies': true,
|
||||
'fetchTransactions': true,
|
||||
'fetchOHLCV': true,
|
||||
},
|
||||
'timeframes': {
|
||||
'1m': '1',
|
||||
'5m': '5',
|
||||
'15m': '15',
|
||||
'30m': '30',
|
||||
'45m': '45',
|
||||
'1h': '60',
|
||||
'2h': '120',
|
||||
'3h': '180',
|
||||
'4h': '240',
|
||||
'1d': 'D',
|
||||
'1w': 'W',
|
||||
'1M': 'M',
|
||||
},
|
||||
'urls': {
|
||||
'logo': 'https://user-images.githubusercontent.com/1294454/27766491-1b0ea956-5eda-11e7-9225-40d67b481b8d.jpg',
|
||||
@@ -62,6 +77,7 @@ module.exports = class exmo extends Exchange {
|
||||
'pair_settings',
|
||||
'ticker',
|
||||
'trades',
|
||||
'candles_history',
|
||||
],
|
||||
},
|
||||
'private': {
|
||||
@@ -69,6 +85,8 @@ module.exports = class exmo extends Exchange {
|
||||
'user_info',
|
||||
'order_create',
|
||||
'order_cancel',
|
||||
'stop_market_order_create',
|
||||
'stop_market_order_cancel',
|
||||
'user_open_orders',
|
||||
'user_trades',
|
||||
'user_cancelled_orders',
|
||||
@@ -103,86 +121,90 @@ module.exports = class exmo extends Exchange {
|
||||
'error': '',
|
||||
'data': {
|
||||
'limits': [
|
||||
{ 'pair': 'EXM/USDT', 'min_q': '1', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '100000' },
|
||||
{ 'pair': 'EXM/ETH', 'min_q': '1', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '5000' },
|
||||
{ 'pair': 'ALGO/EXM', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.001', 'max_p': '10000', 'min_a': '1', 'max_a': '50000000' },
|
||||
{ 'pair': 'ALGO/BTC', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.000001', 'max_a': '50' },
|
||||
{ 'pair': 'ATOM/EXM', 'min_q': '1', 'max_q': '500000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '200', 'max_a': '50000000' },
|
||||
{ 'pair': 'ATOM/BTC', 'min_q': '1', 'max_q': '500000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'BTC/USD', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '1', 'max_p': '30000', 'min_a': '1', 'max_a': '500000' },
|
||||
{ 'pair': 'BTC/KZT', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '1000', 'max_p': '12000000', 'min_a': '1000', 'max_a': '100000000' },
|
||||
{ 'pair': 'ETH/KZT', 'min_q': '0.001', 'max_q': '5000', 'min_p': '4', 'max_p': '40000000', 'min_a': '3', 'max_a': '500000' },
|
||||
{ 'pair': 'USDT/KZT', 'min_q': '1', 'max_q': '500000', 'min_p': '200', 'max_p': '4000', 'min_a': '0.1', 'max_a': '500000' },
|
||||
{ 'pair': 'ONT/EXM', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '200', 'max_a': '15000000' },
|
||||
{ 'pair': 'ONT/BTC', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.00001', 'max_a': '10' },
|
||||
{ 'pair': 'ONT/RUB', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '100', 'max_a': '6000000' },
|
||||
{ 'pair': 'ONT/UAH', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '200', 'max_a': '250000' },
|
||||
{ 'pair': 'ONG/EXM', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '100', 'max_a': '15000000' },
|
||||
{ 'pair': 'ONG/BTC', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.00001', 'max_a': '10' },
|
||||
{ 'pair': 'ONG/RUB', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '100', 'max_a': '250000' },
|
||||
{ 'pair': 'ONG/UAH', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '50', 'max_a': '6000000' },
|
||||
{ 'pair': 'CRON/BTC', 'min_q': '1', 'max_q': '100000', 'min_p': '0.0000001', 'max_p': '1', 'min_a': '0.00001', 'max_a': '100' },
|
||||
{ 'pair': 'CRON/ETH', 'min_q': '1', 'max_q': '100000', 'min_p': '0.0000001', 'max_p': '10', 'min_a': '0.00001', 'max_a': '5000' },
|
||||
{ 'pair': 'CRON/USDT', 'min_q': '1', 'max_q': '100000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.001', 'max_a': '500000' },
|
||||
{ 'pair': 'CRON/EXM', 'min_q': '1', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '100000' },
|
||||
{ 'pair': 'BTC/RUB', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '1', 'max_p': '2000000', 'min_a': '10', 'max_a': '50000000' },
|
||||
{ 'pair': 'BTC/EUR', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '1', 'max_p': '30000', 'min_a': '1', 'max_a': '500000' },
|
||||
{ 'pair': 'BTC/UAH', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '1', 'max_p': '15000000', 'min_a': '10', 'max_a': '15000000' },
|
||||
{ 'pair': 'BTC/GBP', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '1', 'max_p': '30000', 'min_a': '1', 'max_a': '500000' },
|
||||
{ 'pair': 'ETH/GBP', 'min_q': '0.001', 'max_q': '5000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '3', 'max_a': '500000' },
|
||||
{ 'pair': 'XRP/GBP', 'min_q': '1', 'max_q': '5000000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.001', 'max_a': '500000' },
|
||||
{ 'pair': 'USDT/GBP', 'min_q': '1', 'max_q': '500000', 'min_p': '0.5', 'max_p': '10', 'min_a': '0.1', 'max_a': '500000' },
|
||||
{ 'pair': 'BTC/PLN', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '1', 'max_p': '20000000', 'min_a': '50', 'max_a': '2000000' },
|
||||
{ 'pair': 'BTC/TRY', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '1', 'max_p': '800000', 'min_a': '40', 'max_a': '6000000' },
|
||||
{ 'pair': 'BTC/KZT', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '1000', 'max_p': '12000000', 'min_a': '1000', 'max_a': '100000000' },
|
||||
{ 'pair': 'BTC/USDT', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '0.01', 'max_p': '30000', 'min_a': '3', 'max_a': '500000' },
|
||||
{ 'pair': 'ETH/BTC', 'min_q': '0.001', 'max_q': '5000', 'min_p': '0.00000001', 'max_p': '10', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'ETH/USD', 'min_q': '0.001', 'max_q': '5000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '3', 'max_a': '500000' },
|
||||
{ 'pair': 'ETH/RUB', 'min_q': '0.001', 'max_q': '5000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '150', 'max_a': '50000000' },
|
||||
{ 'pair': 'XRP/BTC', 'min_q': '1', 'max_q': '100000', 'min_p': '0.0000001', 'max_p': '1', 'min_a': '0.00001', 'max_a': '100' },
|
||||
{ 'pair': 'XRP/USD', 'min_q': '1', 'max_q': '100000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.001', 'max_a': '500000' },
|
||||
{ 'pair': 'XRP/RUB', 'min_q': '1', 'max_q': '100000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '50000000' },
|
||||
{ 'pair': 'XRP/BTC', 'min_q': '1', 'max_q': '5000000', 'min_p': '0.0000001', 'max_p': '1', 'min_a': '0.00001', 'max_a': '100' },
|
||||
{ 'pair': 'XRP/USD', 'min_q': '1', 'max_q': '5000000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.001', 'max_a': '500000' },
|
||||
{ 'pair': 'XRP/RUB', 'min_q': '1', 'max_q': '5000000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '50000000' },
|
||||
{ 'pair': 'ADA/BTC', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'ADA/ETH', 'min_q': '0.01', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '10', 'min_a': '0.001', 'max_a': '5000' },
|
||||
{ 'pair': 'ADA/USD', 'min_q': '0.01', 'max_q': '10000000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '500000' },
|
||||
{ 'pair': 'BCH/USD', 'min_q': '0.003', 'max_q': '10000', 'min_p': '0.00000001', 'max_p': '30000', 'min_a': '0.0001', 'max_a': '500000' },
|
||||
{ 'pair': 'BCH/RUB', 'min_q': '0.003', 'max_q': '10000', 'min_p': '0.00000001', 'max_p': '2000000', 'min_a': '0.0001', 'max_a': '50000000' },
|
||||
{ 'pair': 'BCH/EUR', 'min_q': '0.003', 'max_q': '100000', 'min_p': '0.01', 'max_p': '300000', 'min_a': '3', 'max_a': '500000' },
|
||||
{ 'pair': 'BCH/UAH', 'min_q': '0.003', 'max_q': '100000', 'min_p': '0.1', 'max_p': '30000', 'min_a': '10', 'max_a': '15000000' },
|
||||
{ 'pair': 'BCH/BTC', 'min_q': '0.003', 'max_q': '10000', 'min_p': '0.00000001', 'max_p': '5', 'min_a': '0.0001', 'max_a': '100' },
|
||||
{ 'pair': 'BCH/ETH', 'min_q': '0.003', 'max_q': '10000', 'min_p': '0.0000001', 'max_p': '200', 'min_a': '0.0001', 'max_a': '5000' },
|
||||
{ 'pair': 'BCH/USDT', 'min_q': '0.003', 'max_q': '100000', 'min_p': '0.01', 'max_p': '5000', 'min_a': '3', 'max_a': '500000' },
|
||||
{ 'pair': 'ALGO/USDT', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '1', 'max_a': '500000' },
|
||||
{ 'pair': 'ALGO/RUB', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.000001', 'max_p': '10000', 'min_a': '1', 'max_a': '50000000' },
|
||||
{ 'pair': 'ALGO/EUR', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '1', 'max_a': '500000' },
|
||||
{ 'pair': 'ATOM/USD', 'min_q': '1', 'max_q': '500000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.5', 'max_a': '500000' },
|
||||
{ 'pair': 'ATOM/EUR', 'min_q': '1', 'max_q': '500000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.5', 'max_a': '500000' },
|
||||
{ 'pair': 'BCH/USD', 'min_q': '0.003', 'max_q': '5000', 'min_p': '0.00000001', 'max_p': '30000', 'min_a': '0.0001', 'max_a': '500000' },
|
||||
{ 'pair': 'BCH/RUB', 'min_q': '0.003', 'max_q': '5000', 'min_p': '0.00000001', 'max_p': '2000000', 'min_a': '0.0001', 'max_a': '50000000' },
|
||||
{ 'pair': 'BCH/EUR', 'min_q': '0.003', 'max_q': '5000', 'min_p': '0.01', 'max_p': '300000', 'min_a': '3', 'max_a': '500000' },
|
||||
{ 'pair': 'BCH/UAH', 'min_q': '0.003', 'max_q': '5000', 'min_p': '0.1', 'max_p': '30000', 'min_a': '10', 'max_a': '15000000' },
|
||||
{ 'pair': 'BCH/BTC', 'min_q': '0.003', 'max_q': '5000', 'min_p': '0.00000001', 'max_p': '5', 'min_a': '0.0001', 'max_a': '100' },
|
||||
{ 'pair': 'BCH/ETH', 'min_q': '0.003', 'max_q': '5000', 'min_p': '0.0000001', 'max_p': '200', 'min_a': '0.0001', 'max_a': '5000' },
|
||||
{ 'pair': 'BCH/USDT', 'min_q': '0.003', 'max_q': '5000', 'min_p': '0.01', 'max_p': '5000', 'min_a': '3', 'max_a': '500000' },
|
||||
{ 'pair': 'BTCZ/BTC', 'min_q': '100', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'BTG/USD', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '3', 'max_a': '500000' },
|
||||
{ 'pair': 'BTG/BTC', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'BTG/ETH', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.0001', 'max_p': '100', 'min_a': '0.01', 'max_a': '5000' },
|
||||
{ 'pair': 'BTT/RUB', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '0.000001', 'max_a': '100' },
|
||||
{ 'pair': 'BTT/UAH', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '0.000001', 'max_a': '100' },
|
||||
{ 'pair': 'BTT/BTC', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '0.1', 'min_a': '0.00001', 'max_a': '100' },
|
||||
{ 'pair': 'BTG/USD', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '3', 'max_a': '500000' },
|
||||
{ 'pair': 'BTG/BTC', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'BTG/ETH', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.0001', 'max_p': '100', 'min_a': '0.01', 'max_a': '5000' },
|
||||
{ 'pair': 'BTT/RUB', 'min_q': '1', 'max_q': '500000000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '0.000001', 'max_a': '100' },
|
||||
{ 'pair': 'BTT/UAH', 'min_q': '1', 'max_q': '500000000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '0.000001', 'max_a': '100' },
|
||||
{ 'pair': 'BTT/BTC', 'min_q': '1', 'max_q': '500000000', 'min_p': '0.00000001', 'max_p': '0.1', 'min_a': '0.00001', 'max_a': '100' },
|
||||
{ 'pair': 'CRON/BTC', 'min_q': '1', 'max_q': '100000', 'min_p': '0.0000001', 'max_p': '1', 'min_a': '0.00001', 'max_a': '100' },
|
||||
{ 'pair': 'CRON/ETH', 'min_q': '1', 'max_q': '100000', 'min_p': '0.0000001', 'max_p': '10', 'min_a': '0.00001', 'max_a': '5000' },
|
||||
{ 'pair': 'CRON/USDT', 'min_q': '1', 'max_q': '100000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.001', 'max_a': '500000' },
|
||||
{ 'pair': 'CRON/EXM', 'min_q': '1', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '100000' },
|
||||
{ 'pair': 'DAI/USD', 'min_q': '1', 'max_q': '500000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
|
||||
{ 'pair': 'DAI/RUB', 'min_q': '1', 'max_q': '500000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '0.5', 'max_a': '30000000' },
|
||||
{ 'pair': 'DAI/BTC', 'min_q': '1', 'max_q': '500000', 'min_p': '0.0000001', 'max_p': '0.1', 'min_a': '0.00001', 'max_a': '100' },
|
||||
{ 'pair': 'DAI/ETH', 'min_q': '1', 'max_q': '500000', 'min_p': '0.000001', 'max_p': '10', 'min_a': '0.0001', 'max_a': '5000' },
|
||||
{ 'pair': 'DASH/USD', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '3', 'max_a': '500000' },
|
||||
{ 'pair': 'DASH/RUB', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '150', 'max_a': '50000000' },
|
||||
{ 'pair': 'DASH/UAH', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.01', 'max_p': '200000', 'min_a': '10', 'max_a': '15000000' },
|
||||
{ 'pair': 'DASH/BTC', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.0001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'DASH/USDT', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.01', 'max_p': '5000', 'min_a': '3', 'max_a': '500000' },
|
||||
{ 'pair': 'DASH/USD', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '3', 'max_a': '500000' },
|
||||
{ 'pair': 'DASH/RUB', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '150', 'max_a': '50000000' },
|
||||
{ 'pair': 'DASH/UAH', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.01', 'max_p': '200000', 'min_a': '10', 'max_a': '15000000' },
|
||||
{ 'pair': 'DASH/BTC', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.0001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'DASH/USDT', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.01', 'max_p': '5000', 'min_a': '3', 'max_a': '500000' },
|
||||
{ 'pair': 'DCR/RUB', 'min_q': '0.01', 'max_q': '50000', 'min_p': '0.00001', 'max_p': '100000', 'min_a': '0.5', 'max_a': '3000000' },
|
||||
{ 'pair': 'DCR/UAH', 'min_q': '0.01', 'max_q': '50000', 'min_p': '0.00001', 'max_p': '100000', 'min_a': '0.25', 'max_a': '1000000' },
|
||||
{ 'pair': 'DCR/BTC', 'min_q': '0.01', 'max_q': '50000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'DOGE/USD', 'min_q': '100', 'max_q': '1000000000', 'min_p': '0.0000001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '500000' },
|
||||
{ 'pair': 'DOGE/BTC', 'min_q': '100', 'max_q': '100000000', 'min_p': '0.0000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '100' },
|
||||
{ 'pair': 'DXT/USD', 'min_q': '100', 'max_q': '10000000', 'min_p': '0.00001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
|
||||
{ 'pair': 'DXT/BTC', 'min_q': '100', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '100' },
|
||||
{ 'pair': 'EOS/USD', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.01', 'max_p': '1000', 'min_a': '0.5', 'max_a': '500000' },
|
||||
{ 'pair': 'EOS/EUR', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.5', 'max_a': '500000' },
|
||||
{ 'pair': 'EOS/BTC', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'ETC/USD', 'min_q': '0.2', 'max_q': '1000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '0.01', 'max_a': '500000' },
|
||||
{ 'pair': 'ETC/RUB', 'min_q': '0.2', 'max_q': '1000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '0.01', 'max_a': '50000000' },
|
||||
{ 'pair': 'ETC/BTC', 'min_q': '0.2', 'max_q': '1000', 'min_p': '0.0001', 'max_p': '0.5', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'DOGE/USD', 'min_q': '100', 'max_q': '500000000', 'min_p': '0.0000001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '500000' },
|
||||
{ 'pair': 'DOGE/BTC', 'min_q': '100', 'max_q': '500000000', 'min_p': '0.0000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '100' },
|
||||
{ 'pair': 'DXT/USD', 'min_q': '100', 'max_q': '50000000', 'min_p': '0.00001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
|
||||
{ 'pair': 'DXT/BTC', 'min_q': '100', 'max_q': '50000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '100' },
|
||||
{ 'pair': 'EOS/USD', 'min_q': '0.01', 'max_q': '500000', 'min_p': '0.01', 'max_p': '1000', 'min_a': '0.5', 'max_a': '500000' },
|
||||
{ 'pair': 'EOS/EUR', 'min_q': '0.01', 'max_q': '500000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.5', 'max_a': '500000' },
|
||||
{ 'pair': 'EOS/BTC', 'min_q': '0.01', 'max_q': '500000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'ETC/USD', 'min_q': '0.2', 'max_q': '100000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '0.01', 'max_a': '500000' },
|
||||
{ 'pair': 'ETC/RUB', 'min_q': '0.2', 'max_q': '100000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '0.01', 'max_a': '50000000' },
|
||||
{ 'pair': 'ETC/BTC', 'min_q': '0.2', 'max_q': '100000', 'min_p': '0.0001', 'max_p': '0.5', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'ETH/EUR', 'min_q': '0.001', 'max_q': '5000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '3', 'max_a': '500000' },
|
||||
{ 'pair': 'ETH/UAH', 'min_q': '0.001', 'max_q': '5000', 'min_p': '0.01', 'max_p': '1000000', 'min_a': '90', 'max_a': '15000000' },
|
||||
{ 'pair': 'ETH/PLN', 'min_q': '0.001', 'max_q': '5000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '50', 'max_a': '2000000' },
|
||||
{ 'pair': 'ETH/TRY', 'min_q': '0.001', 'max_q': '5000', 'min_p': '0.1', 'max_p': '80000', 'min_a': '10', 'max_a': '6000000' },
|
||||
{ 'pair': 'ETH/KZT', 'min_q': '0.001', 'max_q': '5000', 'min_p': '4', 'max_p': '40000000', 'min_a': '3', 'max_a': '500000' },
|
||||
{ 'pair': 'ETH/USDT', 'min_q': '0.001', 'max_q': '5000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '3', 'max_a': '500000' },
|
||||
{ 'pair': 'ETH/LTC', 'min_q': '0.001', 'max_q': '5000', 'min_p': '0.00000001', 'max_p': '100000', 'min_a': '0.05', 'max_a': '100000' },
|
||||
{ 'pair': 'ETZ/BTC', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '10' },
|
||||
{ 'pair': 'ETZ/ETH', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.00000001', 'max_p': '100', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'ETZ/USDT', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '1000' },
|
||||
{ 'pair': 'GAS/USD', 'min_q': '0.01', 'max_q': '10000000', 'min_p': '0.01', 'max_p': '50000', 'min_a': '0.1', 'max_a': '500000' },
|
||||
{ 'pair': 'GAS/BTC', 'min_q': '0.01', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'ETZ/BTC', 'min_q': '1', 'max_q': '50000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '10' },
|
||||
{ 'pair': 'ETZ/ETH', 'min_q': '1', 'max_q': '50000000', 'min_p': '0.00000001', 'max_p': '100', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'ETZ/USDT', 'min_q': '1', 'max_q': '50000000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '1000' },
|
||||
{ 'pair': 'EXM/USDT', 'min_q': '1', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '100000' },
|
||||
{ 'pair': 'EXM/ETH', 'min_q': '1', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '5000' },
|
||||
{ 'pair': 'GAS/USD', 'min_q': '0.01', 'max_q': '500000', 'min_p': '0.01', 'max_p': '50000', 'min_a': '0.1', 'max_a': '500000' },
|
||||
{ 'pair': 'GAS/BTC', 'min_q': '0.01', 'max_q': '500000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'GNT/BTC', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'GNT/ETH', 'min_q': '0.01', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '10', 'min_a': '0.01', 'max_a': '5000' },
|
||||
{ 'pair': 'GUSD/USD', 'min_q': '1', 'max_q': '500000', 'min_p': '0.1', 'max_p': '10', 'min_a': '0.1', 'max_a': '500000' },
|
||||
@@ -197,84 +219,94 @@ module.exports = class exmo extends Exchange {
|
||||
{ 'pair': 'KICK/USDT', 'min_q': '1', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '100000' },
|
||||
{ 'pair': 'KICK/BTC', 'min_q': '1', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '0.1', 'min_a': '0.00001', 'max_a': '100' },
|
||||
{ 'pair': 'KICK/ETH', 'min_q': '1', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '5000' },
|
||||
{ 'pair': 'LSK/USD', 'min_q': '0.1', 'max_q': '200000', 'min_p': '0.1', 'max_p': '1000', 'min_a': '1', 'max_a': '500000' },
|
||||
{ 'pair': 'LSK/RUB', 'min_q': '0.1', 'max_q': '200000', 'min_p': '0.001', 'max_p': '100000', 'min_a': '0.5', 'max_a': '50000000' },
|
||||
{ 'pair': 'LSK/BTC', 'min_q': '1', 'max_q': '200000', 'min_p': '0.0000001', 'max_p': '1', 'min_a': '0.0015', 'max_a': '100' },
|
||||
{ 'pair': 'LTC/USD', 'min_q': '0.05', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '3', 'max_a': '500000' },
|
||||
{ 'pair': 'LTC/RUB', 'min_q': '0.05', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '150', 'max_a': '50000000' },
|
||||
{ 'pair': 'LTC/EUR', 'min_q': '0.05', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '3', 'max_a': '500000' },
|
||||
{ 'pair': 'LTC/UAH', 'min_q': '0.05', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '300000', 'min_a': '5', 'max_a': '18000000' },
|
||||
{ 'pair': 'LTC/BTC', 'min_q': '0.05', 'max_q': '1000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'LSK/USD', 'min_q': '0.1', 'max_q': '500000', 'min_p': '0.1', 'max_p': '1000', 'min_a': '1', 'max_a': '500000' },
|
||||
{ 'pair': 'LSK/RUB', 'min_q': '0.1', 'max_q': '500000', 'min_p': '0.001', 'max_p': '100000', 'min_a': '0.5', 'max_a': '50000000' },
|
||||
{ 'pair': 'LSK/BTC', 'min_q': '1', 'max_q': '500000', 'min_p': '0.0000001', 'max_p': '1', 'min_a': '0.0015', 'max_a': '100' },
|
||||
{ 'pair': 'LTC/USD', 'min_q': '0.05', 'max_q': '10000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '3', 'max_a': '500000' },
|
||||
{ 'pair': 'LTC/RUB', 'min_q': '0.05', 'max_q': '10000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '150', 'max_a': '50000000' },
|
||||
{ 'pair': 'LTC/EUR', 'min_q': '0.05', 'max_q': '10000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '3', 'max_a': '500000' },
|
||||
{ 'pair': 'LTC/UAH', 'min_q': '0.05', 'max_q': '10000', 'min_p': '0.01', 'max_p': '300000', 'min_a': '5', 'max_a': '18000000' },
|
||||
{ 'pair': 'LTC/BTC', 'min_q': '0.05', 'max_q': '10000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'MKR/BTC', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '0.0001', 'max_p': '100', 'min_a': '0.000001', 'max_a': '100' },
|
||||
{ 'pair': 'MKR/DAI', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '0.5', 'max_p': '500000', 'min_a': '0.005', 'max_a': '500000' },
|
||||
{ 'pair': 'MNC/USD', 'min_q': '10', 'max_q': '100000000', 'min_p': '0.000001', 'max_p': '10000', 'min_a': '0.01', 'max_a': '100000' },
|
||||
{ 'pair': 'MNC/BTC', 'min_q': '10', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.000001', 'max_a': '100' },
|
||||
{ 'pair': 'MNC/ETH', 'min_q': '10', 'max_q': '100000000', 'min_p': '0.0000001', 'max_p': '10', 'min_a': '0.00001', 'max_a': '1000' },
|
||||
{ 'pair': 'MNC/USD', 'min_q': '10', 'max_q': '500000000', 'min_p': '0.000001', 'max_p': '10000', 'min_a': '0.01', 'max_a': '100000' },
|
||||
{ 'pair': 'MNC/BTC', 'min_q': '10', 'max_q': '500000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.000001', 'max_a': '100' },
|
||||
{ 'pair': 'MNC/ETH', 'min_q': '10', 'max_q': '500000000', 'min_p': '0.0000001', 'max_p': '10', 'min_a': '0.00001', 'max_a': '1000' },
|
||||
{ 'pair': 'MNX/USD', 'min_q': '0.01', 'max_q': '10000000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.5', 'max_a': '500000' },
|
||||
{ 'pair': 'MNX/BTC', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'MNX/ETH', 'min_q': '0.01', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '10', 'min_a': '0.01', 'max_a': '5000' },
|
||||
{ 'pair': 'NEO/USD', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.01', 'max_p': '50000', 'min_a': '0.1', 'max_a': '500000' },
|
||||
{ 'pair': 'NEO/RUB', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.001', 'max_p': '1500000', 'min_a': '50', 'max_a': '50000000' },
|
||||
{ 'pair': 'NEO/BTC', 'min_q': '0.1', 'max_q': '200000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'OMG/USD', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.01', 'max_p': '1000', 'min_a': '0.5', 'max_a': '500000' },
|
||||
{ 'pair': 'OMG/BTC', 'min_q': '1', 'max_q': '100000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'OMG/ETH', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.00000001', 'max_p': '10', 'min_a': '0.01', 'max_a': '5000' },
|
||||
{ 'pair': 'PTI/RUB', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '600000', 'min_a': '10', 'max_a': '600000' },
|
||||
{ 'pair': 'PTI/BTC', 'min_q': '1', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.000001', 'max_a': '10' },
|
||||
{ 'pair': 'PTI/EOS', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.0000001', 'max_p': '5000', 'min_a': '0.01', 'max_a': '20000' },
|
||||
{ 'pair': 'PTI/USDT', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.000001', 'max_p': '10000', 'min_a': '0.01', 'max_a': '100000' },
|
||||
{ 'pair': 'QTUM/USD', 'min_q': '0.1', 'max_q': '200000', 'min_p': '0.00000001', 'max_p': '10000', 'min_a': '0.1', 'max_a': '500000' },
|
||||
{ 'pair': 'QTUM/BTC', 'min_q': '0.1', 'max_q': '200000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '100' },
|
||||
{ 'pair': 'QTUM/ETH', 'min_q': '0.1', 'max_q': '200000', 'min_p': '0.00000001', 'max_p': '100', 'min_a': '0.001', 'max_a': '5000' },
|
||||
{ 'pair': 'NEO/USD', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.01', 'max_p': '50000', 'min_a': '0.1', 'max_a': '500000' },
|
||||
{ 'pair': 'NEO/RUB', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.001', 'max_p': '1500000', 'min_a': '50', 'max_a': '50000000' },
|
||||
{ 'pair': 'NEO/BTC', 'min_q': '0.1', 'max_q': '100000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'OMG/USD', 'min_q': '0.01', 'max_q': '500000', 'min_p': '0.01', 'max_p': '1000', 'min_a': '0.5', 'max_a': '500000' },
|
||||
{ 'pair': 'OMG/BTC', 'min_q': '1', 'max_q': '500000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'OMG/ETH', 'min_q': '0.01', 'max_q': '500000', 'min_p': '0.00000001', 'max_p': '10', 'min_a': '0.01', 'max_a': '5000' },
|
||||
{ 'pair': 'ONG/EXM', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '100', 'max_a': '15000000' },
|
||||
{ 'pair': 'ONG/BTC', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.00001', 'max_a': '10' },
|
||||
{ 'pair': 'ONG/RUB', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '100', 'max_a': '250000' },
|
||||
{ 'pair': 'ONG/UAH', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '50', 'max_a': '6000000' },
|
||||
{ 'pair': 'ONT/EXM', 'min_q': '1', 'max_q': '500000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '200', 'max_a': '15000000' },
|
||||
{ 'pair': 'ONT/BTC', 'min_q': '1', 'max_q': '500000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.00001', 'max_a': '10' },
|
||||
{ 'pair': 'ONT/RUB', 'min_q': '1', 'max_q': '500000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '100', 'max_a': '6000000' },
|
||||
{ 'pair': 'ONT/UAH', 'min_q': '1', 'max_q': '500000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '200', 'max_a': '250000' },
|
||||
{ 'pair': 'PTI/RUB', 'min_q': '1', 'max_q': '50000000', 'min_p': '0.00000001', 'max_p': '600000', 'min_a': '10', 'max_a': '600000' },
|
||||
{ 'pair': 'PTI/BTC', 'min_q': '1', 'max_q': '50000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.000001', 'max_a': '10' },
|
||||
{ 'pair': 'PTI/EOS', 'min_q': '1', 'max_q': '50000000', 'min_p': '0.0000001', 'max_p': '5000', 'min_a': '0.01', 'max_a': '20000' },
|
||||
{ 'pair': 'PTI/USDT', 'min_q': '1', 'max_q': '50000000', 'min_p': '0.000001', 'max_p': '10000', 'min_a': '0.01', 'max_a': '100000' },
|
||||
{ 'pair': 'QTUM/USD', 'min_q': '0.1', 'max_q': '500000', 'min_p': '0.00000001', 'max_p': '10000', 'min_a': '0.1', 'max_a': '500000' },
|
||||
{ 'pair': 'QTUM/BTC', 'min_q': '0.1', 'max_q': '500000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '100' },
|
||||
{ 'pair': 'QTUM/ETH', 'min_q': '0.1', 'max_q': '500000', 'min_p': '0.00000001', 'max_p': '100', 'min_a': '0.001', 'max_a': '5000' },
|
||||
{ 'pair': 'ROOBEE/BTC', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '0.1', 'min_a': '0.00001', 'max_a': '100' },
|
||||
{ 'pair': 'SMART/USD', 'min_q': '10', 'max_q': '10000000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '1', 'max_a': '500000' },
|
||||
{ 'pair': 'SMART/RUB', 'min_q': '10', 'max_q': '10000000', 'min_p': '0.0001', 'max_p': '100000', 'min_a': '10', 'max_a': '50000000' },
|
||||
{ 'pair': 'SMART/EUR', 'min_q': '10', 'max_q': '10000000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '1', 'max_a': '500000' },
|
||||
{ 'pair': 'SMART/BTC', 'min_q': '10', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.00001', 'max_a': '100' },
|
||||
{ 'pair': 'TRX/USD', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '500000' },
|
||||
{ 'pair': 'TRX/RUB', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.000001', 'max_p': '100000', 'min_a': '0.1', 'max_a': '50000000' },
|
||||
{ 'pair': 'TRX/UAH', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.000001', 'max_p': '100000', 'min_a': '0.1', 'max_a': '50000000' },
|
||||
{ 'pair': 'TRX/BTC', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'SMART/USD', 'min_q': '10', 'max_q': '100000000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '1', 'max_a': '500000' },
|
||||
{ 'pair': 'SMART/RUB', 'min_q': '10', 'max_q': '100000000', 'min_p': '0.0001', 'max_p': '100000', 'min_a': '10', 'max_a': '50000000' },
|
||||
{ 'pair': 'SMART/EUR', 'min_q': '10', 'max_q': '100000000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '1', 'max_a': '500000' },
|
||||
{ 'pair': 'SMART/BTC', 'min_q': '10', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.00001', 'max_a': '100' },
|
||||
{ 'pair': 'TRX/USD', 'min_q': '1', 'max_q': '50000000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '500000' },
|
||||
{ 'pair': 'TRX/EUR', 'min_q': '0.01', 'max_q': '50000000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '500000' },
|
||||
{ 'pair': 'TRX/RUB', 'min_q': '1', 'max_q': '50000000', 'min_p': '0.000001', 'max_p': '100000', 'min_a': '0.1', 'max_a': '50000000' },
|
||||
{ 'pair': 'TRX/UAH', 'min_q': '1', 'max_q': '50000000', 'min_p': '0.000001', 'max_p': '100000', 'min_a': '0.1', 'max_a': '50000000' },
|
||||
{ 'pair': 'TRX/BTC', 'min_q': '1', 'max_q': '50000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'USDC/USD', 'min_q': '1', 'max_q': '500000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '3', 'max_a': '500000' },
|
||||
{ 'pair': 'USDC/BTC', 'min_q': '1', 'max_q': '500000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '100' },
|
||||
{ 'pair': 'USDC/ETH', 'min_q': '1', 'max_q': '500000', 'min_p': '0.0000001', 'max_p': '100', 'min_a': '0.001', 'max_a': '1000' },
|
||||
{ 'pair': 'USDC/USDT', 'min_q': '1', 'max_q': '500000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '3', 'max_a': '500000' },
|
||||
{ 'pair': 'USDT/USD', 'min_q': '1', 'max_q': '500000', 'min_p': '0.5', 'max_p': '10', 'min_a': '0.1', 'max_a': '500000' },
|
||||
{ 'pair': 'USDT/RUB', 'min_q': '1', 'max_q': '500000', 'min_p': '0.01', 'max_p': '1000', 'min_a': '10', 'max_a': '50000000' },
|
||||
{ 'pair': 'USDT/EUR', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.1', 'max_p': '10', 'min_a': '0.1', 'max_a': '500000' },
|
||||
{ 'pair': 'USDT/UAH', 'min_q': '0.01', 'max_q': '100000', 'min_p': '1', 'max_p': '3000', 'min_a': '2', 'max_a': '15000000' },
|
||||
{ 'pair': 'USDT/EUR', 'min_q': '0.01', 'max_q': '500000', 'min_p': '0.1', 'max_p': '10', 'min_a': '0.1', 'max_a': '500000' },
|
||||
{ 'pair': 'USDT/UAH', 'min_q': '0.01', 'max_q': '500000', 'min_p': '1', 'max_p': '3000', 'min_a': '2', 'max_a': '15000000' },
|
||||
{ 'pair': 'USDT/KZT', 'min_q': '1', 'max_q': '500000', 'min_p': '200', 'max_p': '4000', 'min_a': '0.1', 'max_a': '500000' },
|
||||
{ 'pair': 'VLX/BTC', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '0.1', 'min_a': '0.00001', 'max_a': '100' },
|
||||
{ 'pair': 'WAVES/USD', 'min_q': '0.5', 'max_q': '10000', 'min_p': '0.001', 'max_p': '3500', 'min_a': '0.5', 'max_a': '500000' },
|
||||
{ 'pair': 'WAVES/RUB', 'min_q': '0.5', 'max_q': '10000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '1', 'max_a': '50000000' },
|
||||
{ 'pair': 'WAVES/BTC', 'min_q': '0.5', 'max_q': '10000', 'min_p': '0.000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '100' },
|
||||
{ 'pair': 'WAVES/ETH', 'min_q': '0.5', 'max_q': '10000', 'min_p': '0.00001', 'max_p': '30', 'min_a': '0.0035', 'max_a': '3500' },
|
||||
{ 'pair': 'XEM/USD', 'min_q': '10', 'max_q': '5000000', 'min_p': '0.00001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
|
||||
{ 'pair': 'XEM/EUR', 'min_q': '10', 'max_q': '5000000', 'min_p': '0.00001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
|
||||
{ 'pair': 'XEM/UAH', 'min_q': '1', 'max_q': '5000000', 'min_p': '0.0001', 'max_p': '30000', 'min_a': '10', 'max_a': '15000000' },
|
||||
{ 'pair': 'XEM/BTC', 'min_q': '10', 'max_q': '5000000', 'min_p': '0.0000001', 'max_p': '1', 'min_a': '0.00015', 'max_a': '100' },
|
||||
{ 'pair': 'XLM/USD', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '500000' },
|
||||
{ 'pair': 'XLM/RUB', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.00001', 'max_p': '100000', 'min_a': '0.1', 'max_a': '50000000' },
|
||||
{ 'pair': 'XLM/TRY', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.00001', 'max_p': '100000', 'min_a': '0.1', 'max_a': '6000000' },
|
||||
{ 'pair': 'XLM/BTC', 'min_q': '1', 'max_q': '200000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'XMR/USD', 'min_q': '0.01', 'max_q': '1000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
|
||||
{ 'pair': 'XMR/RUB', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.001', 'max_p': '600000', 'min_a': '10', 'max_a': '16000000' },
|
||||
{ 'pair': 'XMR/EUR', 'min_q': '0.01', 'max_q': '1000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
|
||||
{ 'pair': 'XMR/UAH', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.001', 'max_p': '300000', 'min_a': '5', 'max_a': '16000000' },
|
||||
{ 'pair': 'XMR/BTC', 'min_q': '0.01', 'max_q': '1000', 'min_p': '0.0001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'XMR/ETH', 'min_q': '0.01', 'max_q': '1000', 'min_p': '0.00000001', 'max_p': '100', 'min_a': '0.001', 'max_a': '5000' },
|
||||
{ 'pair': 'XRP/EUR', 'min_q': '1', 'max_q': '100000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.001', 'max_a': '500000' },
|
||||
{ 'pair': 'XRP/TRY', 'min_q': '1', 'max_q': '100000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '6000000' },
|
||||
{ 'pair': 'XRP/UAH', 'min_q': '1', 'max_q': '100000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '15000000' },
|
||||
{ 'pair': 'XRP/USDT', 'min_q': '1', 'max_q': '100000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.001', 'max_a': '500000' },
|
||||
{ 'pair': 'XRP/ETH', 'min_q': '1', 'max_q': '100000', 'min_p': '0.00000001', 'max_p': '10', 'min_a': '0.00001', 'max_a': '5000' },
|
||||
{ 'pair': 'WAVES/USD', 'min_q': '0.5', 'max_q': '500000', 'min_p': '0.001', 'max_p': '3500', 'min_a': '0.5', 'max_a': '500000' },
|
||||
{ 'pair': 'WAVES/RUB', 'min_q': '0.5', 'max_q': '500000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '1', 'max_a': '50000000' },
|
||||
{ 'pair': 'WAVES/BTC', 'min_q': '0.5', 'max_q': '500000', 'min_p': '0.000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '100' },
|
||||
{ 'pair': 'WAVES/ETH', 'min_q': '0.5', 'max_q': '500000', 'min_p': '0.00001', 'max_p': '30', 'min_a': '0.0035', 'max_a': '3500' },
|
||||
{ 'pair': 'XEM/USD', 'min_q': '10', 'max_q': '10000000', 'min_p': '0.00001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
|
||||
{ 'pair': 'XEM/EUR', 'min_q': '10', 'max_q': '10000000', 'min_p': '0.00001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
|
||||
{ 'pair': 'XEM/UAH', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.0001', 'max_p': '30000', 'min_a': '10', 'max_a': '15000000' },
|
||||
{ 'pair': 'XEM/BTC', 'min_q': '10', 'max_q': '10000000', 'min_p': '0.0000001', 'max_p': '1', 'min_a': '0.00015', 'max_a': '100' },
|
||||
{ 'pair': 'XLM/USD', 'min_q': '0.01', 'max_q': '5000000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '500000' },
|
||||
{ 'pair': 'XLM/RUB', 'min_q': '0.01', 'max_q': '5000000', 'min_p': '0.00001', 'max_p': '100000', 'min_a': '0.1', 'max_a': '50000000' },
|
||||
{ 'pair': 'XLM/TRY', 'min_q': '0.01', 'max_q': '5000000', 'min_p': '0.00001', 'max_p': '100000', 'min_a': '0.1', 'max_a': '6000000' },
|
||||
{ 'pair': 'XLM/BTC', 'min_q': '1', 'max_q': '5000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'XMR/USD', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
|
||||
{ 'pair': 'XMR/RUB', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.001', 'max_p': '600000', 'min_a': '10', 'max_a': '16000000' },
|
||||
{ 'pair': 'XMR/EUR', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
|
||||
{ 'pair': 'XMR/UAH', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.001', 'max_p': '300000', 'min_a': '5', 'max_a': '16000000' },
|
||||
{ 'pair': 'XMR/BTC', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.0001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'XMR/ETH', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.00000001', 'max_p': '100', 'min_a': '0.001', 'max_a': '5000' },
|
||||
{ 'pair': 'XRP/EUR', 'min_q': '1', 'max_q': '5000000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.001', 'max_a': '500000' },
|
||||
{ 'pair': 'XRP/TRY', 'min_q': '1', 'max_q': '5000000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '6000000' },
|
||||
{ 'pair': 'XRP/UAH', 'min_q': '1', 'max_q': '5000000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '15000000' },
|
||||
{ 'pair': 'XRP/USDT', 'min_q': '1', 'max_q': '5000000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.001', 'max_a': '500000' },
|
||||
{ 'pair': 'XRP/ETH', 'min_q': '1', 'max_q': '5000000', 'min_p': '0.00000001', 'max_p': '10', 'min_a': '0.00001', 'max_a': '5000' },
|
||||
{ 'pair': 'XTZ/USD', 'min_q': '0.1', 'max_q': '100000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '100000' },
|
||||
{ 'pair': 'XTZ/RUB', 'min_q': '0.1', 'max_q': '100000', 'min_p': '0.00001', 'max_p': '100000', 'min_a': '0.5', 'max_a': '500000' },
|
||||
{ 'pair': 'XTZ/BTC', 'min_q': '0.1', 'max_q': '100000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.00001', 'max_a': '10' },
|
||||
{ 'pair': 'XTZ/ETH', 'min_q': '0.1', 'max_q': '100000', 'min_p': '0.0000001', 'max_p': '10', 'min_a': '0.0001', 'max_a': '1000' },
|
||||
{ 'pair': 'ZEC/USD', 'min_q': '0.01', 'max_q': '1000', 'min_p': '0.001', 'max_p': '5000', 'min_a': '0.1', 'max_a': '500000' },
|
||||
{ 'pair': 'ZEC/RUB', 'min_q': '0.01', 'max_q': '1000', 'min_p': '0.001', 'max_p': '100000', 'min_a': '0.1', 'max_a': '50000000' },
|
||||
{ 'pair': 'ZEC/EUR', 'min_q': '0.01', 'max_q': '1000', 'min_p': '0.001', 'max_p': '5000', 'min_a': '0.1', 'max_a': '500000' },
|
||||
{ 'pair': 'ZEC/BTC', 'min_q': '0.01', 'max_q': '1000', 'min_p': '0.00001', 'max_p': '10', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'ZEC/USD', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.001', 'max_p': '5000', 'min_a': '0.1', 'max_a': '500000' },
|
||||
{ 'pair': 'ZEC/RUB', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.001', 'max_p': '100000', 'min_a': '0.1', 'max_a': '50000000' },
|
||||
{ 'pair': 'ZEC/EUR', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.001', 'max_p': '5000', 'min_a': '0.1', 'max_a': '500000' },
|
||||
{ 'pair': 'ZEC/BTC', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.00001', 'max_p': '10', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'ZRX/USD', 'min_q': '0.01', 'max_q': '10000000', 'min_p': '0.00001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
|
||||
{ 'pair': 'ZRX/BTC', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
|
||||
{ 'pair': 'ZRX/ETH', 'min_q': '0.01', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '10', 'min_a': '0.01', 'max_a': '5000' },
|
||||
@@ -337,6 +369,8 @@ module.exports = class exmo extends Exchange {
|
||||
{ 'prov': 'CRON', 'dep': '0%', 'wd': '5 CRON' },
|
||||
{ 'prov': 'ONT', 'dep': '0%', 'wd': '1 ONT' },
|
||||
{ 'prov': 'ONG', 'dep': '0%', 'wd': '5 ONG' },
|
||||
{ 'prov': 'ALGO', 'dep': '0%', 'wd': '0.01 ALGO' },
|
||||
{ 'prov': 'ATOM', 'dep': '0%', 'wd': '' },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -345,9 +379,10 @@ module.exports = class exmo extends Exchange {
|
||||
'items': [
|
||||
{ 'prov': 'EX-CODE', 'dep': '', 'wd': '0.2%' },
|
||||
{ 'prov': 'Payeer', 'dep': '3.95%', 'wd': '-' },
|
||||
{ 'prov': 'AdvCash', 'dep': '0%', 'wd': '3.99%' },
|
||||
{ 'prov': 'AdvCash', 'dep': '0%', 'wd': '3.49%' },
|
||||
{ 'prov': 'Visa/MasterCard (Simplex)', 'dep': '4.5% + 0.5 USD', 'wd': '-' },
|
||||
{ 'prov': 'Visa', 'dep': '3.45%', 'wd': '-' },
|
||||
{ 'prov': 'Frick Bank', 'dep': '0 USD', 'wd': '-' },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -355,22 +390,24 @@ module.exports = class exmo extends Exchange {
|
||||
'title': 'EUR',
|
||||
'items': [
|
||||
{ 'prov': 'EX-CODE', 'dep': '', 'wd': '0.2%' },
|
||||
{ 'prov': 'Visa/MasterCard (Simplex)', 'dep': '4.5% + 0.5 EUR', 'wd': '-' },
|
||||
{ 'prov': 'Visa/MasterCard', 'dep': '4.5% + 0.5 EUR', 'wd': '-' },
|
||||
{ 'prov': 'Visa', 'dep': '2.95%', 'wd': '-' },
|
||||
{ 'prov': 'SEPA', 'dep': '10 EUR', 'wd': '50 EUR' },
|
||||
{ 'prov': 'Frick Internal Transfer', 'dep': '0 EUR', 'wd': '-' },
|
||||
{ 'prov': 'SEPA Frick Bank', 'dep': '0 EUR', 'wd': '-' },
|
||||
{ 'prov': 'WIRE Frick Bank', 'dep': '0%', 'wd': '-' },
|
||||
{ 'prov': 'SEPA Weg Ag', 'dep': '-', 'wd': '1 EUR' },
|
||||
],
|
||||
},
|
||||
{
|
||||
'group': 'rub',
|
||||
'title': 'RUB',
|
||||
'items': [
|
||||
{ 'prov': 'Payeer', 'dep': '2.49%', 'wd': '-' },
|
||||
{ 'prov': 'Payeer', 'dep': '2.49%', 'wd': '3.99%' },
|
||||
{ 'prov': 'EX-CODE', 'dep': '', 'wd': '0.2%' },
|
||||
{ 'prov': 'Qiwi', 'dep': '0.99%', 'wd': '2%' },
|
||||
{ 'prov': 'Yandex Money', 'dep': '1.95%', 'wd': '-' },
|
||||
{ 'prov': 'Enfins', 'dep': '0%', 'wd': '1.49%' },
|
||||
{ 'prov': 'AdvCash', 'dep': '0%', 'wd': '2.49%' },
|
||||
{ 'prov': 'Visa/MasterCard', 'dep': '1.99%', 'wd': '4.49% + 60 RUB' },
|
||||
{ 'prov': 'Qiwi', 'dep': '1.49%', 'wd': '2.49%' },
|
||||
{ 'prov': 'Yandex Money', 'dep': '1.49%', 'wd': '-' },
|
||||
{ 'prov': 'AdvCash', 'dep': '0%', 'wd': '3.49%' },
|
||||
{ 'prov': 'Visa/MasterCard', 'dep': '2.99%', 'wd': '3.99% + 60 RUB' },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -378,7 +415,6 @@ module.exports = class exmo extends Exchange {
|
||||
'title': 'PLN',
|
||||
'items': [
|
||||
{ 'prov': 'EX-CODE', 'dep': '', 'wd': '0.2%' },
|
||||
{ 'prov': 'Visa/MasterCard (Simplex)', 'dep': '4.5% + 1 PLN', 'wd': '-' },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -388,6 +424,7 @@ module.exports = class exmo extends Exchange {
|
||||
{ 'prov': 'EX-CODE', 'dep': '', 'wd': '0.2%' },
|
||||
{ 'prov': 'Visa', 'dep': '3.05%', 'wd': '-' },
|
||||
{ 'prov': 'Visa/MasterCard (Simplex)', 'dep': '4.5% + 2 TRY', 'wd': '-' },
|
||||
{ 'prov': 'AdvCash', 'dep': '0%', 'wd': '-' },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -396,17 +433,18 @@ module.exports = class exmo extends Exchange {
|
||||
'items': [
|
||||
{ 'prov': 'EX-CODE', 'dep': '', 'wd': '0.2%' },
|
||||
{ 'prov': 'Terminal', 'dep': '2.6%', 'wd': '-' },
|
||||
{ 'prov': 'Enfins', 'dep': '0%', 'wd': '1.95%' },
|
||||
{ 'prov': 'Visa/MasterCard', 'dep': '1% + 5 UAH', 'wd': '2.99%' },
|
||||
{ 'prov': 'Visa/MasterCard', 'dep': '1% + 5 UAH', 'wd': '-' },
|
||||
{ 'prov': 'Visa/MasterCard EasyTransfer', 'dep': '-', 'wd': '2.99%' },
|
||||
],
|
||||
},
|
||||
{
|
||||
'group': 'kzt',
|
||||
'title': 'KZT',
|
||||
'items': [
|
||||
{ 'prov': 'EX-CODE', 'dep': '', 'wd': '0.2%' },
|
||||
{ 'prov': 'Visa/MasterCard RoyalPay', 'dep': '-', 'wd': '2.99% + 450 KZT' },
|
||||
{ 'prov': 'Visa/MasterCard', 'dep': '3.5%', 'wd': '-' },
|
||||
{ 'prov': 'AdvCash', 'dep': '0%', 'wd': '1.49%' },
|
||||
{ 'prov': 'AdvCash', 'dep': '0%', 'wd': '-' },
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -420,6 +458,7 @@ module.exports = class exmo extends Exchange {
|
||||
'40015': ExchangeError, // API function do not exist
|
||||
'40016': OnMaintenance, // {"result":false,"error":"Error 40016: Maintenance work in progress"}
|
||||
'40017': AuthenticationError, // Wrong API Key
|
||||
'40032': PermissionDenied, // {"result":false,"error":"Error 40032: Access is denied for this API key"}
|
||||
'40034': RateLimitExceeded, // {"result":false,"error":"Error 40034: Access is denied, rate limit is exceeded"}
|
||||
'50052': InsufficientFunds,
|
||||
'50054': InsufficientFunds,
|
||||
@@ -429,6 +468,8 @@ module.exports = class exmo extends Exchange {
|
||||
'50321': InvalidOrder, // Price by order is more than permissible maximum for this pair
|
||||
},
|
||||
'broad': {
|
||||
'range period is too long': BadRequest,
|
||||
'invalid syntax': BadRequest,
|
||||
'API rate limit exceeded': RateLimitExceeded, // {"result":false,"error":"API rate limit exceeded for 99.33.55.224. Retry after 60 sec.","history":[],"begin":1579392000,"end":1579478400}
|
||||
},
|
||||
},
|
||||
@@ -590,8 +631,21 @@ module.exports = class exmo extends Exchange {
|
||||
}
|
||||
|
||||
async fetchMarkets (params = {}) {
|
||||
const fees = await this.fetchTradingFees ();
|
||||
const response = await this.publicGetPairSettings (params);
|
||||
//
|
||||
// {
|
||||
// "EXM_ETH": {
|
||||
// "min_quantity": "1",
|
||||
// "max_quantity": "1000",
|
||||
// "min_price": "1",
|
||||
// "max_price": "1000",
|
||||
// "max_amount": "1000",
|
||||
// "min_amount": "1",
|
||||
// "commission_taker_percent": "0.2",
|
||||
// "commission_maker_percent": "0.2"
|
||||
// },
|
||||
// }
|
||||
//
|
||||
const keys = Object.keys (response);
|
||||
const result = [];
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
@@ -601,6 +655,8 @@ module.exports = class exmo extends Exchange {
|
||||
const [ baseId, quoteId ] = symbol.split ('/');
|
||||
const base = this.safeCurrencyCode (baseId);
|
||||
const quote = this.safeCurrencyCode (quoteId);
|
||||
const taker = this.safeFloat (market, 'commission_taker_percent');
|
||||
const maker = this.safeFloat (market, 'commission_maker_percent');
|
||||
result.push ({
|
||||
'id': id,
|
||||
'symbol': symbol,
|
||||
@@ -609,8 +665,8 @@ module.exports = class exmo extends Exchange {
|
||||
'baseId': baseId,
|
||||
'quoteId': quoteId,
|
||||
'active': true,
|
||||
'taker': fees['taker'],
|
||||
'maker': fees['maker'],
|
||||
'taker': taker / 100,
|
||||
'maker': maker / 100,
|
||||
'limits': {
|
||||
'amount': {
|
||||
'min': this.safeFloat (market, 'min_quantity'),
|
||||
@@ -635,6 +691,74 @@ module.exports = class exmo extends Exchange {
|
||||
return result;
|
||||
}
|
||||
|
||||
async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
|
||||
await this.loadMarkets ();
|
||||
const market = this.market (symbol);
|
||||
const request = {
|
||||
'symbol': market['id'],
|
||||
'resolution': this.timeframes[timeframe],
|
||||
};
|
||||
const options = this.safeValue (this.options, 'fetchOHLCV');
|
||||
const maxLimit = this.safeInteger (options, 'maxLimit', 3000);
|
||||
const duration = this.parseTimeframe (timeframe);
|
||||
const now = this.milliseconds ();
|
||||
if (since === undefined) {
|
||||
if (limit === undefined) {
|
||||
throw new ArgumentsRequired (this.id + ' fetchOHLCV requires a since argument or a limit argument');
|
||||
} else {
|
||||
if (limit > maxLimit) {
|
||||
throw new BadRequest (this.id + ' fetchOHLCV will serve ' + maxLimit.toString () + ' candles at most');
|
||||
}
|
||||
request['from'] = parseInt (now / 1000) - limit * duration - 1;
|
||||
request['to'] = parseInt (now / 1000);
|
||||
}
|
||||
} else {
|
||||
request['from'] = parseInt (since / 1000) - 1;
|
||||
if (limit === undefined) {
|
||||
request['to'] = parseInt (now / 1000);
|
||||
} else {
|
||||
if (limit > maxLimit) {
|
||||
throw new BadRequest (this.id + ' fetchOHLCV will serve ' + maxLimit.toString () + ' candles at most');
|
||||
}
|
||||
const to = this.sum (since, limit * duration * 1000);
|
||||
request['to'] = parseInt (to / 1000);
|
||||
}
|
||||
}
|
||||
const response = await this.publicGetCandlesHistory (this.extend (request, params));
|
||||
//
|
||||
// {
|
||||
// "candles":[
|
||||
// {"t":1584057600000,"o":0.02235144,"c":0.02400233,"h":0.025171,"l":0.02221,"v":5988.34031761},
|
||||
// {"t":1584144000000,"o":0.0240373,"c":0.02367413,"h":0.024399,"l":0.0235,"v":2027.82522329},
|
||||
// {"t":1584230400000,"o":0.02363458,"c":0.02319242,"h":0.0237948,"l":0.02223196,"v":1707.96944997},
|
||||
// ]
|
||||
// }
|
||||
//
|
||||
const candles = this.safeValue (response, 'candles', []);
|
||||
return this.parseOHLCVs (candles, market, timeframe, since, limit);
|
||||
}
|
||||
|
||||
parseOHLCV (ohlcv, market = undefined, timeframe = '5m', since = undefined, limit = undefined) {
|
||||
//
|
||||
// {
|
||||
// "t":1584057600000,
|
||||
// "o":0.02235144,
|
||||
// "c":0.02400233,
|
||||
// "h":0.025171,
|
||||
// "l":0.02221,
|
||||
// "v":5988.34031761
|
||||
// }
|
||||
//
|
||||
return [
|
||||
this.safeInteger (ohlcv, 't'),
|
||||
this.safeFloat (ohlcv, 'o'),
|
||||
this.safeFloat (ohlcv, 'h'),
|
||||
this.safeFloat (ohlcv, 'l'),
|
||||
this.safeFloat (ohlcv, 'c'),
|
||||
this.safeFloat (ohlcv, 'v'),
|
||||
];
|
||||
}
|
||||
|
||||
async fetchBalance (params = {}) {
|
||||
await this.loadMarkets ();
|
||||
const response = await this.privatePostUserInfo (params);
|
||||
@@ -758,8 +882,36 @@ module.exports = class exmo extends Exchange {
|
||||
}
|
||||
|
||||
parseTrade (trade, market = undefined) {
|
||||
//
|
||||
// fetchTrades (public)
|
||||
//
|
||||
// {
|
||||
// "trade_id":165087520,
|
||||
// "date":1587470005,
|
||||
// "type":"buy",
|
||||
// "quantity":"1.004",
|
||||
// "price":"0.02491461",
|
||||
// "amount":"0.02501426"
|
||||
// },
|
||||
//
|
||||
// fetchMyTrades, fetchOrderTrades
|
||||
//
|
||||
// {
|
||||
// "trade_id": 3,
|
||||
// "date": 1435488248,
|
||||
// "type": "buy",
|
||||
// "pair": "BTC_USD",
|
||||
// "order_id": 12345,
|
||||
// "quantity": 1,
|
||||
// "price": 100,
|
||||
// "amount": 100,
|
||||
// "exec_type": "taker",
|
||||
// "commission_amount": "0.02",
|
||||
// "commission_currency": "BTC",
|
||||
// "commission_percent": "0.2"
|
||||
// }
|
||||
//
|
||||
const timestamp = this.safeTimestamp (trade, 'date');
|
||||
let fee = undefined;
|
||||
let symbol = undefined;
|
||||
const id = this.safeString (trade, 'trade_id');
|
||||
const orderId = this.safeString (trade, 'order_id');
|
||||
@@ -768,24 +920,35 @@ module.exports = class exmo extends Exchange {
|
||||
const cost = this.safeFloat (trade, 'amount');
|
||||
const side = this.safeString (trade, 'type');
|
||||
const type = undefined;
|
||||
if (market !== undefined) {
|
||||
const marketId = this.safeString (trade, 'pair');
|
||||
if (marketId !== undefined) {
|
||||
if (marketId in this.markets_by_id) {
|
||||
market = this.markets_by_id[marketId];
|
||||
} else {
|
||||
const [ baseId, quoteId ] = marketId.split ('_');
|
||||
const base = this.safeCurrencyCode (baseId);
|
||||
const quote = this.safeCurrencyCode (quoteId);
|
||||
symbol = base + '/' + quote;
|
||||
}
|
||||
}
|
||||
if ((symbol === undefined) && (market !== undefined)) {
|
||||
symbol = market['symbol'];
|
||||
if (market['taker'] !== market['maker']) {
|
||||
throw new ExchangeError (this.id + ' parseTrade can not deduce proper fee costs, taker and maker fees now differ');
|
||||
}
|
||||
if ((side === 'buy') && (amount !== undefined)) {
|
||||
fee = {
|
||||
'currency': market['base'],
|
||||
'cost': amount * market['taker'],
|
||||
'rate': market['taker'],
|
||||
};
|
||||
} else if ((side === 'sell') && (cost !== undefined)) {
|
||||
fee = {
|
||||
'currency': market['quote'],
|
||||
'cost': cost * market['taker'],
|
||||
'rate': market['taker'],
|
||||
};
|
||||
}
|
||||
const takerOrMaker = this.safeString (trade, 'exec_type');
|
||||
let fee = undefined;
|
||||
const feeCost = this.safeFloat (trade, 'commission_amount');
|
||||
if (feeCost !== undefined) {
|
||||
const feeCurrencyId = this.safeString (trade, 'commission_currency');
|
||||
const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId);
|
||||
let feeRate = this.safeFloat (trade, 'commission_percent');
|
||||
if (feeRate !== undefined) {
|
||||
feeRate /= 1000;
|
||||
}
|
||||
fee = {
|
||||
'cost': feeCost,
|
||||
'currency': feeCurrencyCode,
|
||||
'rate': feeRate,
|
||||
};
|
||||
}
|
||||
return {
|
||||
'id': id,
|
||||
@@ -796,7 +959,7 @@ module.exports = class exmo extends Exchange {
|
||||
'order': orderId,
|
||||
'type': type,
|
||||
'side': side,
|
||||
'takerOrMaker': undefined,
|
||||
'takerOrMaker': takerOrMaker,
|
||||
'price': price,
|
||||
'amount': amount,
|
||||
'cost': cost,
|
||||
@@ -811,6 +974,28 @@ module.exports = class exmo extends Exchange {
|
||||
'pair': market['id'],
|
||||
};
|
||||
const response = await this.publicGetTrades (this.extend (request, params));
|
||||
//
|
||||
// {
|
||||
// "ETH_BTC":[
|
||||
// {
|
||||
// "trade_id":165087520,
|
||||
// "date":1587470005,
|
||||
// "type":"buy",
|
||||
// "quantity":"1.004",
|
||||
// "price":"0.02491461",
|
||||
// "amount":"0.02501426"
|
||||
// },
|
||||
// {
|
||||
// "trade_id":165087369,
|
||||
// "date":1587469938,
|
||||
// "type":"buy",
|
||||
// "quantity":"0.94",
|
||||
// "price":"0.02492348",
|
||||
// "amount":"0.02342807"
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
//
|
||||
const data = this.safeValue (response, market['id'], []);
|
||||
return this.parseTrades (data, market, since, limit);
|
||||
}
|
||||
@@ -968,6 +1153,31 @@ module.exports = class exmo extends Exchange {
|
||||
'order_id': id.toString (),
|
||||
};
|
||||
const response = await this.privatePostOrderTrades (this.extend (request, params));
|
||||
//
|
||||
// {
|
||||
// "type": "buy",
|
||||
// "in_currency": "BTC",
|
||||
// "in_amount": "1",
|
||||
// "out_currency": "USD",
|
||||
// "out_amount": "100",
|
||||
// "trades": [
|
||||
// {
|
||||
// "trade_id": 3,
|
||||
// "date": 1435488248,
|
||||
// "type": "buy",
|
||||
// "pair": "BTC_USD",
|
||||
// "order_id": 12345,
|
||||
// "quantity": 1,
|
||||
// "price": 100,
|
||||
// "amount": 100,
|
||||
// "exec_type": "taker",
|
||||
// "commission_amount": "0.02",
|
||||
// "commission_currency": "BTC",
|
||||
// "commission_percent": "0.2"
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
//
|
||||
const trades = this.safeValue (response, 'trades');
|
||||
return this.parseTrades (trades, market, since, limit);
|
||||
}
|
||||
@@ -1415,9 +1625,10 @@ module.exports = class exmo extends Exchange {
|
||||
if (response === undefined) {
|
||||
return; // fallback to default error handler
|
||||
}
|
||||
if ('result' in response) {
|
||||
if (('result' in response) || ('errmsg' in response)) {
|
||||
//
|
||||
// {"result":false,"error":"Error 50052: Insufficient funds"}
|
||||
// {"s":"error","errmsg":"strconv.ParseInt: parsing \"\": invalid syntax"}
|
||||
//
|
||||
let success = this.safeValue (response, 'result', false);
|
||||
if (typeof success === 'string') {
|
||||
@@ -1429,7 +1640,7 @@ module.exports = class exmo extends Exchange {
|
||||
}
|
||||
if (!success) {
|
||||
let code = undefined;
|
||||
const message = this.safeString (response, 'error');
|
||||
const message = this.safeString2 (response, 'error', 'errmsg');
|
||||
const errorParts = message.split (':');
|
||||
const numParts = errorParts.length;
|
||||
if (numParts > 1) {
|
||||
|
||||
+4
@@ -580,6 +580,7 @@ module.exports = class ftx extends Exchange {
|
||||
// {
|
||||
// "fee": 20.1374935,
|
||||
// "feeRate": 0.0005,
|
||||
// "feeCurrency": "USD",
|
||||
// "future": "EOS-0329",
|
||||
// "id": 11215,
|
||||
// "liquidity": "taker",
|
||||
@@ -626,8 +627,11 @@ module.exports = class ftx extends Exchange {
|
||||
let fee = undefined;
|
||||
const feeCost = this.safeFloat (trade, 'fee');
|
||||
if (feeCost !== undefined) {
|
||||
const feeCurrencyId = this.safeString (trade, 'feeCurrency');
|
||||
const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId);
|
||||
fee = {
|
||||
'cost': feeCost,
|
||||
'currency': feeCurrencyCode,
|
||||
'rate': this.safeFloat (trade, 'feeRate'),
|
||||
};
|
||||
}
|
||||
|
||||
+94
-25
@@ -164,6 +164,26 @@ module.exports = class gateio extends Exchange {
|
||||
|
||||
async fetchMarkets (params = {}) {
|
||||
const response = await this.publicGetMarketinfo (params);
|
||||
//
|
||||
// {
|
||||
// "result":"true",
|
||||
// "pairs":[
|
||||
// {
|
||||
// "usdt_cnyx":{
|
||||
// "decimal_places":3,
|
||||
// "amount_decimal_places":3,
|
||||
// "min_amount":1,
|
||||
// "min_amount_a":1,
|
||||
// "min_amount_b":3,
|
||||
// "fee":0.02,
|
||||
// "trade_disabled":0,
|
||||
// "buy_disabled":0,
|
||||
// "sell_disabled":0
|
||||
// }
|
||||
// },
|
||||
// ]
|
||||
// }
|
||||
//
|
||||
const markets = this.safeValue (response, 'pairs');
|
||||
if (!markets) {
|
||||
throw new ExchangeError (this.id + ' fetchMarkets got an unrecognized response');
|
||||
@@ -190,14 +210,14 @@ module.exports = class gateio extends Exchange {
|
||||
const symbol = base + '/' + quote;
|
||||
const precision = {
|
||||
'amount': 8,
|
||||
'price': details['decimal_places'],
|
||||
'price': this.safeInteger (details, 'decimal_places'),
|
||||
};
|
||||
const amountLimits = {
|
||||
'min': details['min_amount'],
|
||||
'min': this.safeFloat (details, 'min_amount'),
|
||||
'max': undefined,
|
||||
};
|
||||
const priceLimits = {
|
||||
'min': Math.pow (10, -details['decimal_places']),
|
||||
'min': Math.pow (10, -precision['price']),
|
||||
'max': undefined,
|
||||
};
|
||||
const defaultCost = amountLimits['min'] * priceLimits['min'];
|
||||
@@ -211,9 +231,13 @@ module.exports = class gateio extends Exchange {
|
||||
'price': priceLimits,
|
||||
'cost': costLimits,
|
||||
};
|
||||
const active = true;
|
||||
const disabled = this.safeValue (details, 'trade_disabled');
|
||||
const active = !disabled;
|
||||
const uppercaseId = id.toUpperCase ();
|
||||
const fee = this.safeFloat (details, 'fee');
|
||||
result.push ({
|
||||
'id': id,
|
||||
'uppercaseId': uppercaseId,
|
||||
'symbol': symbol,
|
||||
'base': base,
|
||||
'quote': quote,
|
||||
@@ -221,8 +245,8 @@ module.exports = class gateio extends Exchange {
|
||||
'quoteId': quoteId,
|
||||
'info': market,
|
||||
'active': active,
|
||||
'maker': details['fee'] / 100,
|
||||
'taker': details['fee'] / 100,
|
||||
'maker': fee / 100,
|
||||
'taker': fee / 100,
|
||||
'precision': precision,
|
||||
'limits': limits,
|
||||
});
|
||||
@@ -484,22 +508,64 @@ module.exports = class gateio extends Exchange {
|
||||
|
||||
parseOrder (order, market = undefined) {
|
||||
//
|
||||
// {'amount': '0.00000000',
|
||||
// 'currencyPair': 'xlm_usdt',
|
||||
// 'fee': '0.0113766632239302 USDT',
|
||||
// 'feeCurrency': 'USDT',
|
||||
// 'feePercentage': 0.18,
|
||||
// 'feeValue': '0.0113766632239302',
|
||||
// 'filledAmount': '30.14004987',
|
||||
// 'filledRate': 0.2097,
|
||||
// 'initialAmount': '30.14004987',
|
||||
// 'initialRate': '0.2097',
|
||||
// 'left': 0,
|
||||
// 'orderNumber': '998307286',
|
||||
// 'rate': '0.2097',
|
||||
// 'status': 'closed',
|
||||
// 'timestamp': 1531158583,
|
||||
// 'type': 'sell'},
|
||||
// createOrder
|
||||
//
|
||||
// {
|
||||
// "fee": "0 ZEC",
|
||||
// "code": 0,
|
||||
// "rate": "0.0055",
|
||||
// "side": 2,
|
||||
// "type": "buy",
|
||||
// "ctime": 1586460839.138,
|
||||
// "market": "ZEC_BTC",
|
||||
// "result": "true",
|
||||
// "status": "open",
|
||||
// "iceberg": "0",
|
||||
// "message": "Success",
|
||||
// "feeValue": "0",
|
||||
// "filledRate": "0.005500000",
|
||||
// "leftAmount": "0.60607456",
|
||||
// "feeCurrency": "ZEC",
|
||||
// "orderNumber": 10755887009,
|
||||
// "filledAmount": "0",
|
||||
// "feePercentage": 0.002,
|
||||
// "initialAmount": "0.60607456"
|
||||
// }
|
||||
//
|
||||
// {
|
||||
// 'amount': '0.00000000',
|
||||
// 'currencyPair': 'xlm_usdt',
|
||||
// 'fee': '0.0113766632239302 USDT',
|
||||
// 'feeCurrency': 'USDT',
|
||||
// 'feePercentage': 0.18,
|
||||
// 'feeValue': '0.0113766632239302',
|
||||
// 'filledAmount': '30.14004987',
|
||||
// 'filledRate': 0.2097,
|
||||
// 'initialAmount': '30.14004987',
|
||||
// 'initialRate': '0.2097',
|
||||
// 'left': 0,
|
||||
// 'orderNumber': '998307286',
|
||||
// 'rate': '0.2097',
|
||||
// 'status': 'closed',
|
||||
// 'timestamp': 1531158583,
|
||||
// 'type': 'sell'
|
||||
// }
|
||||
//
|
||||
// {
|
||||
// "orderNumber": 10802237760,
|
||||
// "orderType": 1,
|
||||
// "type": "buy",
|
||||
// "rate": "0.54250000",
|
||||
// "amount": "45.55638518",
|
||||
// "total": "24.71433896",
|
||||
// "initialRate": "0.54250000",
|
||||
// "initialAmount": "45.55638518",
|
||||
// "filledRate": "0.54250000",
|
||||
// "filledAmount": "0",
|
||||
// "currencyPair": "nano_usdt",
|
||||
// "timestamp": 1586556143,
|
||||
// "status": "open"
|
||||
// }
|
||||
//
|
||||
const id = this.safeString2 (order, 'orderNumber', 'id');
|
||||
let symbol = undefined;
|
||||
@@ -520,12 +586,15 @@ module.exports = class gateio extends Exchange {
|
||||
} else if (side === '2') {
|
||||
side = 'buy';
|
||||
}
|
||||
const price = this.safeFloat2 (order, 'initialRate', 'price');
|
||||
const price = this.safeFloat2 (order, 'initialRate', 'rate');
|
||||
const average = this.safeFloat (order, 'filledRate');
|
||||
const amount = this.safeFloat2 (order, 'initialAmount', 'amount');
|
||||
const filled = this.safeFloat (order, 'filledAmount');
|
||||
// In the order status response, this field has a different name.
|
||||
const remaining = this.safeFloat2 (order, 'leftAmount', 'left');
|
||||
let remaining = this.safeFloat2 (order, 'leftAmount', 'left');
|
||||
if (remaining === undefined) {
|
||||
remaining = amount - filled;
|
||||
}
|
||||
const feeCost = this.safeFloat (order, 'feeValue');
|
||||
const feeCurrencyId = this.safeString (order, 'feeCurrency');
|
||||
const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId);
|
||||
@@ -651,7 +720,7 @@ module.exports = class gateio extends Exchange {
|
||||
|
||||
async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
||||
if (symbol === undefined) {
|
||||
throw new ArgumentsRequired (this.id + ' fetchMyTrades requires symbol param');
|
||||
throw new ArgumentsRequired (this.id + ' fetchMyTrades requires symbol argument');
|
||||
}
|
||||
await this.loadMarkets ();
|
||||
const market = this.market (symbol);
|
||||
|
||||
+60
-54
@@ -180,8 +180,7 @@ module.exports = class gemini extends Exchange {
|
||||
if (numTables < 2) {
|
||||
throw new NotSupported (error);
|
||||
}
|
||||
// tables[1] = tables[1].replace ("\n", ''); // eslint-disable-line quotes
|
||||
const rows = tables[1].split ("<tr>\n"); // eslint-disable-line quotes
|
||||
const rows = tables[1].split ("\n<tr>\n"); // eslint-disable-line quotes
|
||||
const numRows = rows.length;
|
||||
if (numRows < 2) {
|
||||
throw new NotSupported (error);
|
||||
@@ -192,66 +191,73 @@ module.exports = class gemini extends Exchange {
|
||||
const row = rows[i];
|
||||
const cells = row.split ("</td>\n"); // eslint-disable-line quotes
|
||||
const numCells = cells.length;
|
||||
if (numCells < 7) {
|
||||
if (numCells < 9) {
|
||||
throw new NotSupported (error);
|
||||
}
|
||||
//
|
||||
// [
|
||||
// '<td><code class="prettyprint">btcusd</code>',
|
||||
// '<td>USD', // quote
|
||||
// '<td>BTC', // base
|
||||
// '<td>0.00001 BTC (1e-5)', // min amount
|
||||
// '<td>0.00000001 BTC (1e-8)', // amount min tick size
|
||||
// '<td>0.01 USD', // price min tick size
|
||||
// '</tr>\n'
|
||||
// '<td>BTC', // currency
|
||||
// '<td>0.00001 BTC (1e-5)', // min order size
|
||||
// '<td>0.00000001 BTC (1e-8)', // tick size
|
||||
// '<td>0.01 USD', // usd price increment
|
||||
// '<td>N/A', // btc price increment
|
||||
// '<td>0.0001 ETH (1e-4)', // eth price increment
|
||||
// '<td>0.0001 BCH (1e-4)', // bch price increment
|
||||
// '<td>0.001 LTC (1e-3)', // ltc price increment
|
||||
// '</tr>'
|
||||
// ]
|
||||
//
|
||||
let id = cells[0].replace ('<td>', '');
|
||||
id = id.replace ('<code class="prettyprint">', '');
|
||||
id = id.replace ('</code>', '');
|
||||
let baseId = cells[2].replace ('<td>', '');
|
||||
let quoteId = cells[1].replace ('<td>', '');
|
||||
const minAmountAsString = cells[3].replace ('<td>', '');
|
||||
const amountTickSizeAsString = cells[4].replace ('<td>', '');
|
||||
const priceTickSizeAsString = cells[5].replace ('<td>', '');
|
||||
const minAmount = minAmountAsString.split (' ');
|
||||
const amountPrecision = amountTickSizeAsString.split (' ');
|
||||
const pricePrecision = priceTickSizeAsString.split (' ');
|
||||
baseId = baseId.toLowerCase ();
|
||||
quoteId = quoteId.toLowerCase ();
|
||||
const uppercaseBaseId = cells[0].replace ('<td>', '');
|
||||
const baseId = uppercaseBaseId.toLowerCase ();
|
||||
const base = this.safeCurrencyCode (baseId);
|
||||
const quote = this.safeCurrencyCode (quoteId);
|
||||
const symbol = base + '/' + quote;
|
||||
const precision = {
|
||||
'amount': this.precisionFromString (amountPrecision[0]),
|
||||
'price': this.precisionFromString (pricePrecision[0]),
|
||||
};
|
||||
const active = undefined;
|
||||
result.push ({
|
||||
'id': id,
|
||||
'info': row,
|
||||
'symbol': symbol,
|
||||
'base': base,
|
||||
'quote': quote,
|
||||
'baseId': baseId,
|
||||
'quoteId': quoteId,
|
||||
'active': active,
|
||||
'precision': precision,
|
||||
'limits': {
|
||||
'amount': {
|
||||
'min': parseFloat (minAmount[0]),
|
||||
'max': undefined,
|
||||
const quoteIds = [ 'usd', 'btc', 'eth', 'bch', 'ltc' ];
|
||||
const minAmountString = cells[1].replace ('<td>', '');
|
||||
const minAmountParts = minAmountString.split (' ');
|
||||
const minAmount = this.safeFloat (minAmountParts, 0);
|
||||
const amountPrecisionString = cells[2].replace ('<td>', '');
|
||||
const amountPrecisionParts = amountPrecisionString.split (' ');
|
||||
const amountPrecision = this.precisionFromString (amountPrecisionParts[0]);
|
||||
for (let j = 0; j < quoteIds.length; j++) {
|
||||
const quoteId = quoteIds[j];
|
||||
const quote = this.safeCurrencyCode (quoteId);
|
||||
const pricePrecisionIndex = this.sum (3, j);
|
||||
const pricePrecisionString = cells[pricePrecisionIndex].replace ('<td>', '');
|
||||
if (pricePrecisionString === 'N/A') {
|
||||
continue;
|
||||
}
|
||||
const pricePrecisionParts = pricePrecisionString.split (' ');
|
||||
const pricePrecision = this.precisionFromString (pricePrecisionParts[0]);
|
||||
const symbol = base + '/' + quote;
|
||||
const id = baseId + quoteId;
|
||||
const active = undefined;
|
||||
result.push ({
|
||||
'id': id,
|
||||
'info': row,
|
||||
'symbol': symbol,
|
||||
'base': base,
|
||||
'quote': quote,
|
||||
'baseId': baseId,
|
||||
'quoteId': quoteId,
|
||||
'active': active,
|
||||
'precision': {
|
||||
'amount': amountPrecision,
|
||||
'price': pricePrecision,
|
||||
},
|
||||
'price': {
|
||||
'min': undefined,
|
||||
'max': undefined,
|
||||
'limits': {
|
||||
'amount': {
|
||||
'min': minAmount,
|
||||
'max': undefined,
|
||||
},
|
||||
'price': {
|
||||
'min': undefined,
|
||||
'max': undefined,
|
||||
},
|
||||
'cost': {
|
||||
'min': undefined,
|
||||
'max': undefined,
|
||||
},
|
||||
},
|
||||
'cost': {
|
||||
'min': undefined,
|
||||
'max': undefined,
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
+2019
File diff suppressed because it is too large.
Load diff
+6
-7
@@ -730,14 +730,13 @@ module.exports = class hitbtc extends Exchange {
|
||||
}
|
||||
|
||||
parseOHLCV (ohlcv, market = undefined, timeframe = '1d', since = undefined, limit = undefined) {
|
||||
const timestamp = this.parse8601 (ohlcv['timestamp']);
|
||||
return [
|
||||
timestamp,
|
||||
parseFloat (ohlcv['open']),
|
||||
parseFloat (ohlcv['max']),
|
||||
parseFloat (ohlcv['min']),
|
||||
parseFloat (ohlcv['close']),
|
||||
parseFloat (ohlcv['volume']),
|
||||
this.parse8601 (this.safeString (ohlcv, 'timestamp')),
|
||||
this.safeFloat (ohlcv, 'open'),
|
||||
this.safeFloat (ohlcv, 'max'),
|
||||
this.safeFloat (ohlcv, 'min'),
|
||||
this.safeFloat (ohlcv, 'close'),
|
||||
this.safeFloat (ohlcv, 'volume'),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const hitbtc = require ('./hitbtc');
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
module.exports = class hitbtc2 extends hitbtc {
|
||||
describe () {
|
||||
// this is a temporary stub for backward compatibility
|
||||
// https://github.com/ccxt/ccxt/issues/6678
|
||||
return this.deepExtend (super.describe (), {
|
||||
'id': 'hitbtc2',
|
||||
});
|
||||
}
|
||||
};
|
||||
+27
-1
@@ -163,12 +163,14 @@ module.exports = class huobipro extends Exchange {
|
||||
'exceptions': {
|
||||
'exact': {
|
||||
// err-code
|
||||
'bad-request': BadRequest,
|
||||
'api-not-support-temp-addr': PermissionDenied, // {"status":"error","err-code":"api-not-support-temp-addr","err-msg":"API withdrawal does not support temporary addresses","data":null}
|
||||
'timeout': RequestTimeout, // {"ts":1571653730865,"status":"error","err-code":"timeout","err-msg":"Request Timeout"}
|
||||
'gateway-internal-error': ExchangeNotAvailable, // {"status":"error","err-code":"gateway-internal-error","err-msg":"Failed to load data. Try again later.","data":null}
|
||||
'account-frozen-balance-insufficient-error': InsufficientFunds, // {"status":"error","err-code":"account-frozen-balance-insufficient-error","err-msg":"trade account balance is not enough, left: `0.0027`","data":null}
|
||||
'invalid-amount': InvalidOrder, // eg "Paramemter `amount` is invalid."
|
||||
'order-limitorder-amount-min-error': InvalidOrder, // limit order amount error, min: `0.001`
|
||||
'order-limitorder-amount-max-error': InvalidOrder, // market order amount error, max: `1000000`
|
||||
'order-marketorder-amount-min-error': InvalidOrder, // market order amount error, min: `0.01`
|
||||
'order-limitorder-price-min-error': InvalidOrder, // limit order price error
|
||||
'order-limitorder-price-max-error': InvalidOrder, // limit order price error
|
||||
@@ -331,6 +333,8 @@ module.exports = class huobipro extends Exchange {
|
||||
}
|
||||
|
||||
parseTicker (ticker, market = undefined) {
|
||||
//
|
||||
// fetchTicker
|
||||
//
|
||||
// {
|
||||
// "amount": 26228.672978342216,
|
||||
@@ -346,25 +350,47 @@ module.exports = class huobipro extends Exchange {
|
||||
// "bid": [ 9146.86, 0.080758 ],
|
||||
// }
|
||||
//
|
||||
// fetchTickers
|
||||
// {
|
||||
// symbol: "bhdht",
|
||||
// open: 2.3938,
|
||||
// high: 2.4151,
|
||||
// low: 2.3323,
|
||||
// close: 2.3909,
|
||||
// amount: 628.992,
|
||||
// vol: 1493.71841095,
|
||||
// count: 2088,
|
||||
// bid: 2.3643,
|
||||
// bidSize: 0.7136,
|
||||
// ask: 2.4061,
|
||||
// askSize: 0.4156
|
||||
// }
|
||||
//
|
||||
let symbol = undefined;
|
||||
if (market !== undefined) {
|
||||
symbol = market['symbol'];
|
||||
}
|
||||
const timestamp = this.safeInteger (ticker, 'ts');
|
||||
let bid = undefined;
|
||||
let ask = undefined;
|
||||
let bidVolume = undefined;
|
||||
let ask = undefined;
|
||||
let askVolume = undefined;
|
||||
if ('bid' in ticker) {
|
||||
if (Array.isArray (ticker['bid'])) {
|
||||
bid = this.safeFloat (ticker['bid'], 0);
|
||||
bidVolume = this.safeFloat (ticker['bid'], 1);
|
||||
} else {
|
||||
bid = this.safeFloat (ticker, 'bid');
|
||||
bidVolume = this.safeValue (ticker, 'bidSize');
|
||||
}
|
||||
}
|
||||
if ('ask' in ticker) {
|
||||
if (Array.isArray (ticker['ask'])) {
|
||||
ask = this.safeFloat (ticker['ask'], 0);
|
||||
askVolume = this.safeFloat (ticker['ask'], 1);
|
||||
} else {
|
||||
ask = this.safeFloat (ticker, 'ask');
|
||||
askVolume = this.safeValue (ticker, 'askSize');
|
||||
}
|
||||
}
|
||||
const open = this.safeFloat (ticker, 'open');
|
||||
|
||||
+2
-2
@@ -3,7 +3,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const Exchange = require ('./base/Exchange');
|
||||
const { ExchangeError, AuthenticationError } = require ('./base/errors');
|
||||
const { ExchangeError, AuthenticationError, ArgumentsRequired } = require ('./base/errors');
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -221,7 +221,7 @@ module.exports = class ice3x extends Exchange {
|
||||
const type = this.safeString (params, 'type');
|
||||
if ((type !== 'ask') && (type !== 'bid')) {
|
||||
// eslint-disable-next-line quotes
|
||||
throw new ExchangeError (this.id + " fetchOrderBook requires an exchange-specific extra 'type' param ('bid' or 'ask') when used with a limit");
|
||||
throw new ArgumentsRequired (this.id + " fetchOrderBook requires an exchange-specific extra 'type' param ('bid' or 'ask') when used with a limit");
|
||||
} else {
|
||||
request['items_per_page'] = limit;
|
||||
}
|
||||
|
||||
+3
-3
@@ -362,7 +362,7 @@ module.exports = class indodax extends Exchange {
|
||||
|
||||
async fetchOrder (id, symbol = undefined, params = {}) {
|
||||
if (symbol === undefined) {
|
||||
throw new ExchangeError (this.id + ' fetchOrder requires a symbol');
|
||||
throw new ArgumentsRequired (this.id + ' fetchOrder requires a symbol');
|
||||
}
|
||||
await this.loadMarkets ();
|
||||
const market = this.market (symbol);
|
||||
@@ -409,7 +409,7 @@ module.exports = class indodax extends Exchange {
|
||||
|
||||
async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
||||
if (symbol === undefined) {
|
||||
throw new ExchangeError (this.id + ' fetchOrders requires a symbol');
|
||||
throw new ArgumentsRequired (this.id + ' fetchOrders requires a symbol argument');
|
||||
}
|
||||
await this.loadMarkets ();
|
||||
const request = {};
|
||||
@@ -458,7 +458,7 @@ module.exports = class indodax extends Exchange {
|
||||
}
|
||||
const side = this.safeValue (params, 'side');
|
||||
if (side === undefined) {
|
||||
throw new ExchangeError (this.id + ' cancelOrder requires an extra "side" param');
|
||||
throw new ArgumentsRequired (this.id + ' cancelOrder requires an extra "side" param');
|
||||
}
|
||||
await this.loadMarkets ();
|
||||
const market = this.market (symbol);
|
||||
|
||||
+2
-2
@@ -3,7 +3,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const Exchange = require ('./base/Exchange');
|
||||
const { ExchangeError, AuthenticationError } = require ('./base/errors');
|
||||
const { ExchangeError, AuthenticationError, ArgumentsRequired } = require ('./base/errors');
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -254,7 +254,7 @@ module.exports = class itbit extends Exchange {
|
||||
await this.loadMarkets ();
|
||||
const walletId = this.safeString (params, 'walletId');
|
||||
if (walletId === undefined) {
|
||||
throw new ExchangeError (this.id + ' fetchMyTrades requires a walletId parameter');
|
||||
throw new ArgumentsRequired (this.id + ' fetchMyTrades requires a walletId parameter');
|
||||
}
|
||||
const request = {
|
||||
'walletId': walletId,
|
||||
|
||||
+263
-32
@@ -36,6 +36,7 @@ module.exports = class kraken extends Exchange {
|
||||
'withdraw': true,
|
||||
'fetchLedgerEntry': true,
|
||||
'fetchLedger': true,
|
||||
'fetchOrderTrades': 'emulated',
|
||||
},
|
||||
'marketsByAltname': {},
|
||||
'timeframes': {
|
||||
@@ -54,7 +55,7 @@ module.exports = class kraken extends Exchange {
|
||||
'api': {
|
||||
'public': 'https://api.kraken.com',
|
||||
'private': 'https://api.kraken.com',
|
||||
'zendesk': 'https://support.kraken.com/hc/en-us/articles',
|
||||
'zendesk': 'https://kraken.zendesk.com/api/v2/help_center/en-us/articles', // use the public zendesk api to receive article bodies and bypass new anti-spam protections
|
||||
},
|
||||
'www': 'https://www.kraken.com',
|
||||
'doc': 'https://www.kraken.com/features/api',
|
||||
@@ -149,9 +150,9 @@ module.exports = class kraken extends Exchange {
|
||||
'get': [
|
||||
// we should really refrain from putting fixed fee numbers and stop hardcoding
|
||||
// we will be using their web APIs to scrape all numbers from these articles
|
||||
'205893708-What-is-the-minimum-order-size-',
|
||||
'201396777-What-are-the-deposit-fees-',
|
||||
'201893608-What-are-the-withdrawal-fees-',
|
||||
'205893708', // -What-is-the-minimum-order-size-
|
||||
'360000292886', // -What-are-the-deposit-fees-
|
||||
'201893608', // -What-are-the-withdrawal-fees-
|
||||
],
|
||||
},
|
||||
'public': {
|
||||
@@ -234,12 +235,14 @@ module.exports = class kraken extends Exchange {
|
||||
return this.decimalToPrecision (fee, TRUNCATE, this.markets[symbol]['precision']['amount'], DECIMAL_PLACES);
|
||||
}
|
||||
|
||||
async fetchMinOrderAmounts () {
|
||||
const html = await this.zendeskGet205893708WhatIsTheMinimumOrderSize ();
|
||||
async fetchMinOrderAmounts (params = {}) {
|
||||
const response = await this.zendeskGet205893708 (params);
|
||||
const article = this.safeValue (response, 'article');
|
||||
const html = this.safeString (article, 'body');
|
||||
const parts = html.split ('<td class="wysiwyg-text-align-right">');
|
||||
const numParts = parts.length;
|
||||
if (numParts < 3) {
|
||||
throw new NotSupported (this.id + ' fetchMinOrderAmounts HTML page markup has changed: https://support.kraken.com/hc/en-us/articles/205893708-What-is-the-minimum-order-size-');
|
||||
throw new NotSupported (this.id + ' fetchMinOrderAmounts HTML page markup has changed: https://kraken.zendesk.com/api/v2/help_center/en-us/articles/205893708');
|
||||
}
|
||||
const result = {};
|
||||
// skip the part before the header and the header itself
|
||||
@@ -262,6 +265,52 @@ module.exports = class kraken extends Exchange {
|
||||
|
||||
async fetchMarkets (params = {}) {
|
||||
const response = await this.publicGetAssetPairs (params);
|
||||
//
|
||||
// {
|
||||
// "error":[],
|
||||
// "result":{
|
||||
// "ADAETH":{
|
||||
// "altname":"ADAETH",
|
||||
// "wsname":"ADA\/ETH",
|
||||
// "aclass_base":"currency",
|
||||
// "base":"ADA",
|
||||
// "aclass_quote":"currency",
|
||||
// "quote":"XETH",
|
||||
// "lot":"unit",
|
||||
// "pair_decimals":7,
|
||||
// "lot_decimals":8,
|
||||
// "lot_multiplier":1,
|
||||
// "leverage_buy":[],
|
||||
// "leverage_sell":[],
|
||||
// "fees":[
|
||||
// [0,0.26],
|
||||
// [50000,0.24],
|
||||
// [100000,0.22],
|
||||
// [250000,0.2],
|
||||
// [500000,0.18],
|
||||
// [1000000,0.16],
|
||||
// [2500000,0.14],
|
||||
// [5000000,0.12],
|
||||
// [10000000,0.1]
|
||||
// ],
|
||||
// "fees_maker":[
|
||||
// [0,0.16],
|
||||
// [50000,0.14],
|
||||
// [100000,0.12],
|
||||
// [250000,0.1],
|
||||
// [500000,0.08],
|
||||
// [1000000,0.06],
|
||||
// [2500000,0.04],
|
||||
// [5000000,0.02],
|
||||
// [10000000,0]
|
||||
// ],
|
||||
// "fee_volume_currency":"ZUSD",
|
||||
// "margin_call":80,
|
||||
// "margin_stop":40
|
||||
// },
|
||||
// }
|
||||
// }
|
||||
//
|
||||
const fetchMinOrderAmounts = this.safeValue (this.options, 'fetchMinOrderAmounts', false);
|
||||
let limits = {};
|
||||
if (fetchMinOrderAmounts) {
|
||||
@@ -441,6 +490,13 @@ module.exports = class kraken extends Exchange {
|
||||
};
|
||||
}
|
||||
|
||||
parseBidAsk (bidask, priceKey = 0, amountKey = 1) {
|
||||
const price = this.safeFloat (bidask, priceKey);
|
||||
const amount = this.safeFloat (bidask, amountKey);
|
||||
const timestamp = this.safeInteger (bidask, 2);
|
||||
return [ price, amount, timestamp ];
|
||||
}
|
||||
|
||||
async fetchOrderBook (symbol, limit = undefined, params = {}) {
|
||||
await this.loadMarkets ();
|
||||
const market = this.market (symbol);
|
||||
@@ -454,7 +510,27 @@ module.exports = class kraken extends Exchange {
|
||||
request['count'] = limit; // 100
|
||||
}
|
||||
const response = await this.publicGetDepth (this.extend (request, params));
|
||||
const orderbook = response['result'][market['id']];
|
||||
//
|
||||
// {
|
||||
// "error":[],
|
||||
// "result":{
|
||||
// "XETHXXBT":{
|
||||
// "asks":[
|
||||
// ["0.023480","4.000",1586321307],
|
||||
// ["0.023490","50.095",1586321306],
|
||||
// ["0.023500","28.535",1586321302],
|
||||
// ],
|
||||
// "bids":[
|
||||
// ["0.023470","59.580",1586321307],
|
||||
// ["0.023460","20.000",1586321301],
|
||||
// ["0.023440","67.832",1586321306],
|
||||
// ]
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
const result = this.safeValue (response, 'result', {});
|
||||
const orderbook = this.safeValue (result, market['id']);
|
||||
return this.parseOrderBook (orderbook);
|
||||
}
|
||||
|
||||
@@ -708,26 +784,46 @@ module.exports = class kraken extends Exchange {
|
||||
}
|
||||
|
||||
parseTrade (trade, market = undefined) {
|
||||
//
|
||||
// fetchTrades (public)
|
||||
//
|
||||
// [
|
||||
// "0.032310", // price
|
||||
// "4.28169434", // amount
|
||||
// 1541390792.763, // timestamp
|
||||
// "s", // sell or buy
|
||||
// "l", // limit or market
|
||||
// ""
|
||||
// ]
|
||||
//
|
||||
// fetchOrderTrades (private)
|
||||
//
|
||||
// {
|
||||
// id: 'TIMIRG-WUNNE-RRJ6GT', // injected from outside
|
||||
// ordertxid: 'OQRPN2-LRHFY-HIFA7D',
|
||||
// postxid: 'TKH2SE-M7IF5-CFI7LT',
|
||||
// pair: 'USDCUSDT',
|
||||
// time: 1586340086.457,
|
||||
// type: 'sell',
|
||||
// ordertype: 'market',
|
||||
// price: '0.99860000',
|
||||
// cost: '22.16892001',
|
||||
// fee: '0.04433784',
|
||||
// vol: '22.20000000',
|
||||
// margin: '0.00000000',
|
||||
// misc: ''
|
||||
// }
|
||||
//
|
||||
let timestamp = undefined;
|
||||
let side = undefined;
|
||||
let type = undefined;
|
||||
let price = undefined;
|
||||
let amount = undefined;
|
||||
let cost = undefined;
|
||||
let id = undefined;
|
||||
let order = undefined;
|
||||
let fee = undefined;
|
||||
const marketId = this.safeString (trade, 'pair');
|
||||
const foundMarket = this.findMarketByAltnameOrId (marketId);
|
||||
let symbol = undefined;
|
||||
if (foundMarket !== undefined) {
|
||||
market = foundMarket;
|
||||
} else if (marketId !== undefined) {
|
||||
// delisted market ids go here
|
||||
market = this.getDelistedMarketById (marketId);
|
||||
}
|
||||
if (market !== undefined) {
|
||||
symbol = market['symbol'];
|
||||
}
|
||||
if (Array.isArray (trade)) {
|
||||
timestamp = this.safeTimestamp (trade, 2);
|
||||
side = (trade[3] === 's') ? 'sell' : 'buy';
|
||||
@@ -738,17 +834,27 @@ module.exports = class kraken extends Exchange {
|
||||
if (tradeLength > 6) {
|
||||
id = this.safeString (trade, 6); // artificially added as per #1794
|
||||
}
|
||||
} else if (typeof trade === 'string') {
|
||||
id = trade;
|
||||
} else if ('ordertxid' in trade) {
|
||||
const marketId = this.safeString (trade, 'pair');
|
||||
const foundMarket = this.findMarketByAltnameOrId (marketId);
|
||||
if (foundMarket !== undefined) {
|
||||
market = foundMarket;
|
||||
} else if (marketId !== undefined) {
|
||||
// delisted market ids go here
|
||||
market = this.getDelistedMarketById (marketId);
|
||||
}
|
||||
order = trade['ordertxid'];
|
||||
id = this.safeString2 (trade, 'id', 'postxid');
|
||||
timestamp = this.safeTimestamp (trade, 'time');
|
||||
side = trade['type'];
|
||||
type = trade['ordertype'];
|
||||
side = this.safeString (trade, 'type');
|
||||
type = this.safeString (trade, 'ordertype');
|
||||
price = this.safeFloat (trade, 'price');
|
||||
amount = this.safeFloat (trade, 'vol');
|
||||
if ('fee' in trade) {
|
||||
let currency = undefined;
|
||||
if (market) {
|
||||
if (market !== undefined) {
|
||||
currency = market['quote'];
|
||||
}
|
||||
fee = {
|
||||
@@ -757,6 +863,14 @@ module.exports = class kraken extends Exchange {
|
||||
};
|
||||
}
|
||||
}
|
||||
if (market !== undefined) {
|
||||
symbol = market['symbol'];
|
||||
}
|
||||
if (price !== undefined) {
|
||||
if (amount !== undefined) {
|
||||
cost = price * amount;
|
||||
}
|
||||
}
|
||||
return {
|
||||
'id': id,
|
||||
'order': order,
|
||||
@@ -769,7 +883,7 @@ module.exports = class kraken extends Exchange {
|
||||
'takerOrMaker': undefined,
|
||||
'price': price,
|
||||
'amount': amount,
|
||||
'cost': price * amount,
|
||||
'cost': cost,
|
||||
'fee': fee,
|
||||
};
|
||||
}
|
||||
@@ -986,6 +1100,11 @@ module.exports = class kraken extends Exchange {
|
||||
const status = this.parseOrderStatus (this.safeString (order, 'status'));
|
||||
const id = this.safeString (order, 'id');
|
||||
const clientOrderId = this.safeString (order, 'userref');
|
||||
const rawTrades = this.safeValue (order, 'trades');
|
||||
let trades = undefined;
|
||||
if (rawTrades !== undefined) {
|
||||
trades = this.parseTrades (rawTrades, market, undefined, undefined, { 'order': id });
|
||||
}
|
||||
return {
|
||||
'id': id,
|
||||
'clientOrderId': clientOrderId,
|
||||
@@ -1004,8 +1123,7 @@ module.exports = class kraken extends Exchange {
|
||||
'average': average,
|
||||
'remaining': remaining,
|
||||
'fee': fee,
|
||||
// 'trades': this.parseTrades (order['trades'], market),
|
||||
'trades': undefined,
|
||||
'trades': trades,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1026,16 +1144,129 @@ module.exports = class kraken extends Exchange {
|
||||
|
||||
async fetchOrder (id, symbol = undefined, params = {}) {
|
||||
await this.loadMarkets ();
|
||||
const response = await this.privatePostQueryOrders (this.extend ({
|
||||
const clientOrderId = this.safeValue2 (params, 'userref', 'clientOrderId');
|
||||
const request = {
|
||||
'trades': true, // whether or not to include trades in output (optional, default false)
|
||||
'txid': id, // do not comma separate a list of ids - use fetchOrdersByIds instead
|
||||
// 'txid': id, // do not comma separate a list of ids - use fetchOrdersByIds instead
|
||||
// 'userref': 'optional', // restrict results to given user reference id (optional)
|
||||
}, params));
|
||||
const orders = response['result'];
|
||||
};
|
||||
let query = params;
|
||||
if (clientOrderId !== undefined) {
|
||||
request['userref'] = clientOrderId;
|
||||
query = this.omit (params, [ 'userref', 'clientOrderId' ]);
|
||||
} else {
|
||||
request['txid'] = id;
|
||||
}
|
||||
const response = await this.privatePostQueryOrders (this.extend (request, query));
|
||||
//
|
||||
// {
|
||||
// "error":[],
|
||||
// "result":{
|
||||
// "OTLAS3-RRHUF-NDWH5A":{
|
||||
// "refid":null,
|
||||
// "userref":null,
|
||||
// "status":"closed",
|
||||
// "reason":null,
|
||||
// "opentm":1586822919.3342,
|
||||
// "closetm":1586822919.365,
|
||||
// "starttm":0,
|
||||
// "expiretm":0,
|
||||
// "descr":{
|
||||
// "pair":"XBTUSDT",
|
||||
// "type":"sell",
|
||||
// "ordertype":"market",
|
||||
// "price":"0",
|
||||
// "price2":"0",
|
||||
// "leverage":"none",
|
||||
// "order":"sell 0.21804000 XBTUSDT @ market",
|
||||
// "close":""
|
||||
// },
|
||||
// "vol":"0.21804000",
|
||||
// "vol_exec":"0.21804000",
|
||||
// "cost":"1493.9",
|
||||
// "fee":"3.8",
|
||||
// "price":"6851.5",
|
||||
// "stopprice":"0.00000",
|
||||
// "limitprice":"0.00000",
|
||||
// "misc":"",
|
||||
// "oflags":"fciq",
|
||||
// "trades":["TT5UC3-GOIRW-6AZZ6R"]
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
const orders = this.safeValue (response, 'result', []);
|
||||
const order = this.parseOrder (this.extend ({ 'id': id }, orders[id]));
|
||||
return this.extend ({ 'info': response }, order);
|
||||
}
|
||||
|
||||
async fetchOrderTrades (id, symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
||||
const orderTrades = this.safeValue (params, 'trades');
|
||||
const tradeIds = [];
|
||||
if (orderTrades === undefined) {
|
||||
throw new ArgumentsRequired (this.id + " fetchOrderTrades requires a unified order structure in the params argument or a 'trades' param (an array of trade id strings)");
|
||||
} else {
|
||||
for (let i = 0; i < orderTrades.length; i++) {
|
||||
const orderTrade = orderTrades[i];
|
||||
if (typeof orderTrade === 'string') {
|
||||
tradeIds.push (orderTrade);
|
||||
} else {
|
||||
tradeIds.push (orderTrade['id']);
|
||||
}
|
||||
}
|
||||
}
|
||||
await this.loadMarkets ();
|
||||
const options = this.safeValue (this.options, 'fetchOrderTrades', {});
|
||||
const batchSize = this.safeInteger (options, 'batchSize', 20);
|
||||
let numBatches = parseInt (tradeIds / batchSize);
|
||||
numBatches = this.sum (numBatches, 1);
|
||||
const numTradeIds = tradeIds.length;
|
||||
let result = [];
|
||||
for (let j = 0; j < numBatches; j++) {
|
||||
const requestIds = [];
|
||||
for (let k = 0; k < batchSize; k++) {
|
||||
const index = this.sum (j * batchSize, k);
|
||||
if (index < numTradeIds) {
|
||||
requestIds.push (tradeIds[index]);
|
||||
}
|
||||
}
|
||||
const request = {
|
||||
'txid': requestIds.join (','),
|
||||
};
|
||||
const response = await this.privatePostQueryTrades (request);
|
||||
//
|
||||
// {
|
||||
// error: [],
|
||||
// result: {
|
||||
// 'TIMIRG-WUNNE-RRJ6GT': {
|
||||
// ordertxid: 'OQRPN2-LRHFY-HIFA7D',
|
||||
// postxid: 'TKH2SE-M7IF5-CFI7LT',
|
||||
// pair: 'USDCUSDT',
|
||||
// time: 1586340086.457,
|
||||
// type: 'sell',
|
||||
// ordertype: 'market',
|
||||
// price: '0.99860000',
|
||||
// cost: '22.16892001',
|
||||
// fee: '0.04433784',
|
||||
// vol: '22.20000000',
|
||||
// margin: '0.00000000',
|
||||
// misc: ''
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
const rawTrades = this.safeValue (response, 'result');
|
||||
const ids = Object.keys (rawTrades);
|
||||
for (let i = 0; i < ids.length; i++) {
|
||||
rawTrades[ids[i]]['id'] = ids[i];
|
||||
}
|
||||
const trades = this.parseTrades (rawTrades, undefined, since, limit);
|
||||
const tradesFilteredBySymbol = this.filterBySymbol (trades, symbol);
|
||||
result = this.arrayConcat (result, tradesFilteredBySymbol);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
async fetchOrdersByIds (ids, symbol = undefined, params = {}) {
|
||||
await this.loadMarkets ();
|
||||
const response = await this.privatePostQueryOrders (this.extend ({
|
||||
@@ -1248,11 +1479,11 @@ module.exports = class kraken extends Exchange {
|
||||
}
|
||||
|
||||
async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
|
||||
await this.loadMarkets ();
|
||||
// https://www.kraken.com/en-us/help/api#deposit-status
|
||||
if (code === undefined) {
|
||||
throw new ArgumentsRequired (this.id + ' fetchDeposits requires a currency code argument');
|
||||
}
|
||||
await this.loadMarkets ();
|
||||
const currency = this.currency (code);
|
||||
const request = {
|
||||
'asset': currency['id'],
|
||||
@@ -1275,11 +1506,11 @@ module.exports = class kraken extends Exchange {
|
||||
}
|
||||
|
||||
async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
|
||||
await this.loadMarkets ();
|
||||
// https://www.kraken.com/en-us/help/api#withdraw-status
|
||||
if (code === undefined) {
|
||||
throw new ArgumentsRequired (this.id + ' fetchWithdrawals requires a currency code argument');
|
||||
}
|
||||
await this.loadMarkets ();
|
||||
const currency = this.currency (code);
|
||||
const request = {
|
||||
'asset': currency['id'],
|
||||
@@ -1328,7 +1559,7 @@ module.exports = class kraken extends Exchange {
|
||||
}
|
||||
method = this.options['depositMethods'][code][0]['method'];
|
||||
} else {
|
||||
throw new ExchangeError (this.id + ' fetchDepositAddress() requires an extra `method` parameter. Use fetchDepositMethods ("' + code + '") to get a list of available deposit methods or enable the exchange property .options["cacheDepositMethodsOnFetchDepositAddress"] = true');
|
||||
throw new ArgumentsRequired (this.id + ' fetchDepositAddress() requires an extra `method` parameter. Use fetchDepositMethods ("' + code + '") to get a list of available deposit methods or enable the exchange property .options["cacheDepositMethodsOnFetchDepositAddress"] = true');
|
||||
}
|
||||
}
|
||||
const request = {
|
||||
|
||||
+121
-41
@@ -69,7 +69,9 @@ module.exports = class kucoin extends Exchange {
|
||||
'public': {
|
||||
'get': [
|
||||
'timestamp',
|
||||
'status',
|
||||
'symbols',
|
||||
'markets',
|
||||
'market/allTickers',
|
||||
'market/orderbook/level{level}',
|
||||
'market/orderbook/level2',
|
||||
@@ -81,6 +83,9 @@ module.exports = class kucoin extends Exchange {
|
||||
'market/stats',
|
||||
'currencies',
|
||||
'currencies/{currency}',
|
||||
'prices',
|
||||
'mark-price/{symbol}/current',
|
||||
'margin/config',
|
||||
],
|
||||
'post': [
|
||||
'bullet-public',
|
||||
@@ -92,6 +97,10 @@ module.exports = class kucoin extends Exchange {
|
||||
'accounts/{accountId}',
|
||||
'accounts/{accountId}/ledgers',
|
||||
'accounts/{accountId}/holds',
|
||||
'accounts/transferable',
|
||||
'sub/user',
|
||||
'sub-accounts',
|
||||
'sub-accounts/{subUserId}',
|
||||
'deposit-addresses',
|
||||
'deposits',
|
||||
'hist-deposits',
|
||||
@@ -101,8 +110,20 @@ module.exports = class kucoin extends Exchange {
|
||||
'withdrawals/quotas',
|
||||
'orders',
|
||||
'orders/{orderId}',
|
||||
'limit/orders',
|
||||
'fills',
|
||||
'limit/fills',
|
||||
'margin/account',
|
||||
'margin/borrow',
|
||||
'margin/borrow/outstanding',
|
||||
'margin/borrow/borrow/repaid',
|
||||
'margin/lend/active',
|
||||
'margin/lend/done',
|
||||
'margin/lend/trade/unsettled',
|
||||
'margin/lend/trade/settled',
|
||||
'margin/lend/assets',
|
||||
'margin/market',
|
||||
'margin/margin/trade/last',
|
||||
],
|
||||
'post': [
|
||||
'accounts',
|
||||
@@ -111,11 +132,19 @@ module.exports = class kucoin extends Exchange {
|
||||
'deposit-addresses',
|
||||
'withdrawals',
|
||||
'orders',
|
||||
'orders/multi',
|
||||
'margin/borrow',
|
||||
'margin/repay/all',
|
||||
'margin/repay/single',
|
||||
'margin/lend',
|
||||
'margin/toggle-auto-lend',
|
||||
'bullet-private',
|
||||
],
|
||||
'delete': [
|
||||
'withdrawals/{withdrawalId}',
|
||||
'orders',
|
||||
'orders/{orderId}',
|
||||
'margin/lend/{orderId}',
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -247,18 +276,20 @@ module.exports = class kucoin extends Exchange {
|
||||
async fetchMarkets (params = {}) {
|
||||
const response = await this.publicGetSymbols (params);
|
||||
//
|
||||
// { quoteCurrency: 'BTC',
|
||||
// symbol: 'KCS-BTC',
|
||||
// quoteMaxSize: '9999999',
|
||||
// quoteIncrement: '0.000001',
|
||||
// baseMinSize: '0.01',
|
||||
// quoteMinSize: '0.00001',
|
||||
// enableTrading: true,
|
||||
// priceIncrement: '0.00000001',
|
||||
// name: 'KCS-BTC',
|
||||
// baseIncrement: '0.01',
|
||||
// baseMaxSize: '9999999',
|
||||
// baseCurrency: 'KCS' }
|
||||
// {
|
||||
// quoteCurrency: 'BTC',
|
||||
// symbol: 'KCS-BTC',
|
||||
// quoteMaxSize: '9999999',
|
||||
// quoteIncrement: '0.000001',
|
||||
// baseMinSize: '0.01',
|
||||
// quoteMinSize: '0.00001',
|
||||
// enableTrading: true,
|
||||
// priceIncrement: '0.00000001',
|
||||
// name: 'KCS-BTC',
|
||||
// baseIncrement: '0.01',
|
||||
// baseMaxSize: '9999999',
|
||||
// baseCurrency: 'KCS'
|
||||
// }
|
||||
//
|
||||
const data = response['data'];
|
||||
const result = [];
|
||||
@@ -344,20 +375,27 @@ module.exports = class kucoin extends Exchange {
|
||||
async fetchAccounts (params = {}) {
|
||||
const response = await this.privateGetAccounts (params);
|
||||
//
|
||||
// { code: "200000",
|
||||
// data: [ { balance: "0.00009788",
|
||||
// {
|
||||
// code: "200000",
|
||||
// data: [
|
||||
// {
|
||||
// balance: "0.00009788",
|
||||
// available: "0.00009788",
|
||||
// holds: "0",
|
||||
// currency: "BTC",
|
||||
// id: "5c6a4fd399a1d81c4f9cc4d0",
|
||||
// type: "trade" },
|
||||
// ...,
|
||||
// { balance: "0.00000001",
|
||||
// holds: "0",
|
||||
// currency: "BTC",
|
||||
// id: "5c6a4fd399a1d81c4f9cc4d0",
|
||||
// type: "trade"
|
||||
// },
|
||||
// {
|
||||
// balance: "0.00000001",
|
||||
// available: "0.00000001",
|
||||
// holds: "0",
|
||||
// currency: "ETH",
|
||||
// id: "5c6a49ec99a1d819392e8e9f",
|
||||
// type: "trade" } ] }
|
||||
// holds: "0",
|
||||
// currency: "ETH",
|
||||
// id: "5c6a49ec99a1d819392e8e9f",
|
||||
// type: "trade"
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
//
|
||||
const data = this.safeValue (response, 'data');
|
||||
const result = [];
|
||||
@@ -641,30 +679,72 @@ module.exports = class kucoin extends Exchange {
|
||||
};
|
||||
}
|
||||
|
||||
async fetchL3OrderBook (symbol, limit = undefined, params = {}) {
|
||||
return await this.fetchOrderBook (symbol, limit, { 'level': 3 });
|
||||
}
|
||||
|
||||
async fetchOrderBook (symbol, limit = undefined, params = {}) {
|
||||
let level = '2';
|
||||
if (limit !== undefined) {
|
||||
if ((limit !== 20) && (limit !== 100)) {
|
||||
throw new ExchangeError (this.id + ' fetchOrderBook limit argument must be undefined, 20 or 100');
|
||||
const level = this.safeInteger (params, 'level', 2);
|
||||
let levelLimit = level.toString ();
|
||||
if (level === '2') {
|
||||
if (limit !== undefined) {
|
||||
if ((limit !== 20) && (limit !== 100)) {
|
||||
throw new ExchangeError (this.id + ' fetchOrderBook limit argument must be undefined, 20 or 100');
|
||||
}
|
||||
levelLimit += '_' + limit.toString ();
|
||||
}
|
||||
level += '_' + limit.toString ();
|
||||
}
|
||||
await this.loadMarkets ();
|
||||
const marketId = this.marketId (symbol);
|
||||
const request = this.extend ({ 'symbol': marketId, 'level': level }, params);
|
||||
const response = await this.publicGetMarketOrderbookLevelLevel (request);
|
||||
const request = { 'symbol': marketId, 'level': levelLimit };
|
||||
const response = await this.publicGetMarketOrderbookLevelLevel (this.extend (request, params));
|
||||
//
|
||||
// { sequence: '1547731421688',
|
||||
// asks: [ [ '5c419328ef83c75456bd615c', '0.9', '0.09' ], ... ],
|
||||
// bids: [ [ '5c419328ef83c75456bd615c', '0.9', '0.09' ], ... ], }
|
||||
// 'market/orderbook/level2'
|
||||
// 'market/orderbook/level2_20'
|
||||
// 'market/orderbook/level2_100'
|
||||
//
|
||||
const data = response['data'];
|
||||
// {
|
||||
// "code":"200000",
|
||||
// "data":{
|
||||
// "sequence":"1583235112106",
|
||||
// "asks":[
|
||||
// // ...
|
||||
// ["0.023197","12.5067468"],
|
||||
// ["0.023194","1.8"],
|
||||
// ["0.023191","8.1069672"]
|
||||
// ],
|
||||
// "bids":[
|
||||
// ["0.02319","1.6000002"],
|
||||
// ["0.023189","2.2842325"],
|
||||
// ],
|
||||
// "time":1586584067274
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// 'market/orderbook/level3'
|
||||
//
|
||||
// {
|
||||
// "code":"200000",
|
||||
// "data":{
|
||||
// "sequence":"1583731857120",
|
||||
// "asks":[
|
||||
// // id, price, size, timestamp in nanoseconds
|
||||
// ["5e915f8acd26670009675300","6925.7","0.2","1586585482194286069"],
|
||||
// ["5e915f8ace35a200090bba48","6925.7","0.001","1586585482229569826"],
|
||||
// ["5e915f8a8857740009ca7d33","6926","0.00001819","1586585482149148621"],
|
||||
// ],
|
||||
// "bids":[
|
||||
// ["5e915f8acca406000ac88194","6925.6","0.05","1586585482384384842"],
|
||||
// ["5e915f93cd26670009676075","6925.6","0.08","1586585491334914600"],
|
||||
// ["5e915f906aa6e200099b49f6","6925.4","0.2","1586585488941126340"],
|
||||
// ],
|
||||
// "time":1586585492487
|
||||
// }
|
||||
// }
|
||||
//
|
||||
const data = this.safeValue (response, 'data', {});
|
||||
const timestamp = this.safeInteger (data, 'time');
|
||||
// level can be a string such as 2_20 or 2_100
|
||||
const levelString = this.safeString (request, 'level');
|
||||
const levelParts = levelString.split ('_');
|
||||
const offset = parseInt (levelParts[0]);
|
||||
const orderbook = this.parseOrderBook (data, timestamp, 'bids', 'asks', offset - 2, offset - 1);
|
||||
const orderbook = this.parseOrderBook (data, timestamp, 'bids', 'asks', level - 2, level - 1);
|
||||
orderbook['nonce'] = this.safeInteger (data, 'sequence');
|
||||
return orderbook;
|
||||
}
|
||||
@@ -715,7 +795,7 @@ module.exports = class kucoin extends Exchange {
|
||||
'datetime': this.iso8601 (timestamp),
|
||||
'fee': undefined,
|
||||
'status': 'open',
|
||||
'clientOid': clientOid,
|
||||
'clientOrderId': clientOid,
|
||||
'info': data,
|
||||
};
|
||||
if (!this.safeValue (params, 'quoteAmount')) {
|
||||
|
||||
+21
-1
@@ -18,11 +18,12 @@ module.exports = class kuna extends acx {
|
||||
'has': {
|
||||
'CORS': false,
|
||||
'fetchTickers': true,
|
||||
'fetchOHLCV': false,
|
||||
'fetchOHLCV': 'emulated',
|
||||
'fetchOpenOrders': true,
|
||||
'fetchMyTrades': true,
|
||||
'withdraw': false,
|
||||
},
|
||||
'timeframes': undefined,
|
||||
'urls': {
|
||||
'referral': 'https://kuna.io?r=kunaid-gvfihe8az7o4',
|
||||
'logo': 'https://user-images.githubusercontent.com/1294454/31697638-912824fa-b3c1-11e7-8c36-cf9606eb94ac.jpg',
|
||||
@@ -191,4 +192,23 @@ module.exports = class kuna extends acx {
|
||||
const response = await this.privateGetTradesMy (this.extend (request, params));
|
||||
return this.parseTrades (response, market, since, limit);
|
||||
}
|
||||
|
||||
async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limits = undefined, params = {}) {
|
||||
await this.loadMarkets ();
|
||||
const trades = await this.fetchTrades (symbol, since, limits, params);
|
||||
const ohlcvc = this.buildOHLCVC (trades, timeframe, since, limits);
|
||||
const result = [];
|
||||
for (let i = 0; i < ohlcvc.length; i++) {
|
||||
const ohlcv = ohlcvc[i];
|
||||
result.push ([
|
||||
ohlcv[0],
|
||||
ohlcv[1],
|
||||
ohlcv[2],
|
||||
ohlcv[3],
|
||||
ohlcv[4],
|
||||
ohlcv[5],
|
||||
]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
+59
-22
@@ -3,7 +3,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const Exchange = require ('./base/Exchange');
|
||||
const { ExchangeError } = require ('./base/errors');
|
||||
const { ExchangeError, AuthenticationError, BadSymbol, InvalidOrder, InsufficientFunds } = require ('./base/errors');
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -14,6 +14,7 @@ module.exports = class lakebtc extends Exchange {
|
||||
'name': 'LakeBTC',
|
||||
'countries': [ 'US' ],
|
||||
'version': 'api_v2',
|
||||
'rateLimit': 1000,
|
||||
'has': {
|
||||
'CORS': true,
|
||||
'createMarketOrder': false,
|
||||
@@ -55,6 +56,14 @@ module.exports = class lakebtc extends Exchange {
|
||||
'taker': 0.2 / 100,
|
||||
},
|
||||
},
|
||||
'exceptions': {
|
||||
'broad': {
|
||||
'Signature': AuthenticationError,
|
||||
'invalid symbol': BadSymbol,
|
||||
'Volume doit': InvalidOrder,
|
||||
'insufficient_balance': InsufficientFunds,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -248,40 +257,68 @@ module.exports = class lakebtc extends Exchange {
|
||||
} else {
|
||||
this.checkRequiredCredentials ();
|
||||
const nonce = this.nonce ();
|
||||
const nonceAsString = nonce.toString ();
|
||||
const requestId = this.seconds ();
|
||||
let queryParams = '';
|
||||
if ('params' in params) {
|
||||
const paramsList = params['params'];
|
||||
queryParams = paramsList.join (',');
|
||||
const stringParams = [];
|
||||
for (let i = 0; i < paramsList.length; i++) {
|
||||
let param = paramsList[i];
|
||||
if (typeof paramsList !== 'string') {
|
||||
param = param.toString ();
|
||||
}
|
||||
stringParams.push (param);
|
||||
}
|
||||
queryParams = stringParams.join (',');
|
||||
body = {
|
||||
'method': path,
|
||||
'params': params['params'],
|
||||
'id': requestId,
|
||||
};
|
||||
} else {
|
||||
body = {
|
||||
'method': path,
|
||||
'params': '',
|
||||
'id': requestId,
|
||||
};
|
||||
}
|
||||
const query = this.urlencode ({
|
||||
'tonce': nonce,
|
||||
'accesskey': this.apiKey,
|
||||
'requestmethod': method.toLowerCase (),
|
||||
'id': nonce,
|
||||
'method': path,
|
||||
'params': queryParams,
|
||||
});
|
||||
body = this.json ({
|
||||
'method': path,
|
||||
'params': queryParams,
|
||||
'id': nonce,
|
||||
});
|
||||
body = this.json (body);
|
||||
let query = [
|
||||
'tonce=' + nonceAsString,
|
||||
'accesskey=' + this.apiKey,
|
||||
'requestmethod=' + method.toLowerCase (),
|
||||
'id=' + requestId.toString (),
|
||||
'method=' + path,
|
||||
'params=' + queryParams,
|
||||
];
|
||||
query = query.join ('&');
|
||||
const signature = this.hmac (this.encode (query), this.encode (this.secret), 'sha1');
|
||||
const auth = this.encode (this.apiKey + ':' + signature);
|
||||
const signature64 = this.decode (this.stringToBase64 (auth));
|
||||
headers = {
|
||||
'Json-Rpc-Tonce': nonce.toString (),
|
||||
'Authorization': 'Basic ' + this.decode (this.stringToBase64 (auth)),
|
||||
'Json-Rpc-Tonce': nonceAsString,
|
||||
'Authorization': 'Basic ' + signature64,
|
||||
'Content-Type': 'application/json',
|
||||
};
|
||||
}
|
||||
return { 'url': url, 'method': method, 'body': body, 'headers': headers };
|
||||
}
|
||||
|
||||
async request (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
|
||||
const response = await this.fetch2 (path, api, method, params, headers, body);
|
||||
if ('error' in response) {
|
||||
throw new ExchangeError (this.id + ' ' + this.json (response));
|
||||
handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
|
||||
if (response === undefined) {
|
||||
return; // fallback to the default error handler
|
||||
}
|
||||
//
|
||||
// {"error":"Failed to submit order: invalid symbol"}
|
||||
// {"error":"Failed to submit order: La validation a échoué : Volume doit être supérieur ou égal à 1.0"}
|
||||
// {"error":"Failed to submit order: insufficient_balance"}
|
||||
//
|
||||
const feedback = this.id + ' ' + body;
|
||||
const error = this.safeString (response, 'error');
|
||||
if (error !== undefined) {
|
||||
this.throwBroadlyMatchedException (this.exceptions['broad'], error, feedback);
|
||||
throw new ExchangeError (feedback); // unknown message
|
||||
}
|
||||
return response;
|
||||
}
|
||||
};
|
||||
+3
-3
@@ -3,7 +3,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const Exchange = require ('./base/Exchange');
|
||||
const { ExchangeError, DDoSProtection, AuthenticationError, InvalidOrder } = require ('./base/errors');
|
||||
const { ExchangeError, DDoSProtection, AuthenticationError, InvalidOrder, ArgumentsRequired } = require ('./base/errors');
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -339,10 +339,10 @@ module.exports = class lbank extends Exchange {
|
||||
await this.loadMarkets ();
|
||||
const market = this.market (symbol);
|
||||
if (since === undefined) {
|
||||
throw new ExchangeError (this.id + ' fetchOHLCV requires a `since` argument');
|
||||
throw new ArgumentsRequired (this.id + ' fetchOHLCV requires a `since` argument');
|
||||
}
|
||||
if (limit === undefined) {
|
||||
throw new ExchangeError (this.id + ' fetchOHLCV requires a `limit` argument');
|
||||
throw new ArgumentsRequired (this.id + ' fetchOHLCV requires a `limit` argument');
|
||||
}
|
||||
const request = {
|
||||
'symbol': market['id'],
|
||||
|
||||
+64
-8
@@ -177,7 +177,7 @@ module.exports = class liquid extends Exchange {
|
||||
}
|
||||
|
||||
async fetchMarkets (params = {}) {
|
||||
const markets = await this.publicGetProducts ();
|
||||
const spot = await this.publicGetProducts (params);
|
||||
//
|
||||
// [
|
||||
// {
|
||||
@@ -208,20 +208,69 @@ module.exports = class liquid extends Exchange {
|
||||
// },
|
||||
// ]
|
||||
//
|
||||
const perpetual = await this.publicGetProducts ({ 'perpetual': '1' });
|
||||
//
|
||||
// [
|
||||
// {
|
||||
// "id": "603",
|
||||
// "product_type": "Perpetual",
|
||||
// "code": "CASH",
|
||||
// "name": null,
|
||||
// "market_ask": "1143900",
|
||||
// "market_bid": "1143250",
|
||||
// "currency": "JPY",
|
||||
// "currency_pair_code": "P-BTCJPY",
|
||||
// "pusher_channel": "product_cash_p-btcjpy_603",
|
||||
// "taker_fee": "0.0",
|
||||
// "maker_fee": "0.0",
|
||||
// "low_market_bid": "1124450.0",
|
||||
// "high_market_ask": "1151750.0",
|
||||
// "volume_24h": "0.1756",
|
||||
// "last_price_24h": "1129850.0",
|
||||
// "last_traded_price": "1144700.0",
|
||||
// "last_traded_quantity": "0.014",
|
||||
// "quoted_currency": "JPY",
|
||||
// "base_currency": "P-BTC",
|
||||
// "tick_size": "50.0",
|
||||
// "perpetual_enabled": true,
|
||||
// "index_price": "1142636.03935",
|
||||
// "mark_price": "1143522.18417",
|
||||
// "funding_rate": "0.00033",
|
||||
// "fair_price": "1143609.31009",
|
||||
// "timestamp": "1581558659.195353100",
|
||||
// },
|
||||
// ]
|
||||
//
|
||||
const currencies = await this.fetchCurrencies ();
|
||||
const currenciesByCode = this.indexBy (currencies, 'code');
|
||||
const result = [];
|
||||
const markets = this.arrayConcat (spot, perpetual);
|
||||
for (let i = 0; i < markets.length; i++) {
|
||||
const market = markets[i];
|
||||
const id = market['id'].toString ();
|
||||
const baseId = market['base_currency'];
|
||||
const quoteId = market['quoted_currency'];
|
||||
const id = this.safeString (market, 'id');
|
||||
const baseId = this.safeString (market, 'base_currency');
|
||||
const quoteId = this.safeString (market, 'quoted_currency');
|
||||
const productType = this.safeString (market, 'product_type');
|
||||
let type = 'spot';
|
||||
let spot = true;
|
||||
let swap = false;
|
||||
if (productType === 'Perpetual') {
|
||||
spot = false;
|
||||
swap = true;
|
||||
type = 'swap';
|
||||
}
|
||||
const base = this.safeCurrencyCode (baseId);
|
||||
const quote = this.safeCurrencyCode (quoteId);
|
||||
const symbol = base + '/' + quote;
|
||||
let symbol = undefined;
|
||||
if (swap) {
|
||||
symbol = this.safeString (market, 'currency_pair_code');
|
||||
} else {
|
||||
symbol = base + '/' + quote;
|
||||
}
|
||||
const maker = this.safeFloat (market, 'maker_fee');
|
||||
const taker = this.safeFloat (market, 'taker_fee');
|
||||
const active = !market['disabled'];
|
||||
const disabled = this.safeValue (market, 'disabled', false);
|
||||
const active = !disabled;
|
||||
const baseCurrency = this.safeValue (currenciesByCode, base);
|
||||
const quoteCurrency = this.safeValue (currenciesByCode, quote);
|
||||
const precision = {
|
||||
@@ -265,6 +314,9 @@ module.exports = class liquid extends Exchange {
|
||||
'quote': quote,
|
||||
'baseId': baseId,
|
||||
'quoteId': quoteId,
|
||||
'type': type,
|
||||
'spot': spot,
|
||||
'swap': swap,
|
||||
'maker': maker,
|
||||
'taker': taker,
|
||||
'limits': limits,
|
||||
@@ -393,7 +445,7 @@ module.exports = class liquid extends Exchange {
|
||||
return this.parseTicker (response, market);
|
||||
}
|
||||
|
||||
parseTrade (trade, market) {
|
||||
parseTrade (trade, market = undefined) {
|
||||
// { id: 12345,
|
||||
// quantity: "6.789",
|
||||
// price: "98765.4321",
|
||||
@@ -420,13 +472,17 @@ module.exports = class liquid extends Exchange {
|
||||
}
|
||||
}
|
||||
const id = this.safeString (trade, 'id');
|
||||
let symbol = undefined;
|
||||
if (market !== undefined) {
|
||||
symbol = market['symbol'];
|
||||
}
|
||||
return {
|
||||
'info': trade,
|
||||
'id': id,
|
||||
'order': orderId,
|
||||
'timestamp': timestamp,
|
||||
'datetime': this.iso8601 (timestamp),
|
||||
'symbol': market['symbol'],
|
||||
'symbol': symbol,
|
||||
'type': undefined,
|
||||
'side': side,
|
||||
'takerOrMaker': takerOrMaker,
|
||||
|
||||
+19
-7
@@ -439,7 +439,18 @@ module.exports = class livecoin extends Exchange {
|
||||
}
|
||||
}
|
||||
let symbol = undefined;
|
||||
if (market !== undefined) {
|
||||
const marketId = this.safeString (trade, 'symbol');
|
||||
if (marketId !== undefined) {
|
||||
if (marketId in this.markets_by_id) {
|
||||
market = this.markets_by_id[marketId];
|
||||
} else {
|
||||
const [ baseId, quoteId ] = marketId.split ('/');
|
||||
const base = this.safeCurrencyCode (baseId);
|
||||
const quote = this.safeCurrencyCode (quoteId);
|
||||
symbol = base + '/' + quote;
|
||||
}
|
||||
}
|
||||
if ((symbol === undefined) && (market !== undefined)) {
|
||||
symbol = market['symbol'];
|
||||
}
|
||||
return {
|
||||
@@ -460,16 +471,17 @@ module.exports = class livecoin extends Exchange {
|
||||
}
|
||||
|
||||
async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
||||
if (symbol === undefined) {
|
||||
throw new ArgumentsRequired (this.id + ' fetchMyTrades requires a symbol argument');
|
||||
}
|
||||
await this.loadMarkets ();
|
||||
const market = this.market (symbol);
|
||||
const request = {
|
||||
'currencyPair': market['id'],
|
||||
// orderDesc': 'true', // or 'false', if true then new orders will be first, otherwise old orders will be first.
|
||||
// 'currencyPair': market['id'],
|
||||
// 'orderDesc': 'true', // or 'false', if true then new orders will be first, otherwise old orders will be first.
|
||||
// 'offset': 0, // page offset, position of the first item on the page
|
||||
};
|
||||
let market = undefined;
|
||||
if (symbol !== undefined) {
|
||||
market = this.market (symbol);
|
||||
request['currencyPair'] = market['id'];
|
||||
}
|
||||
if (limit !== undefined) {
|
||||
request['limit'] = limit;
|
||||
}
|
||||
|
||||
+3
-3
@@ -399,17 +399,17 @@ module.exports = class mercado extends Exchange {
|
||||
if (code === 'BRL') {
|
||||
const account_ref = ('account_ref' in params);
|
||||
if (!account_ref) {
|
||||
throw new ExchangeError (this.id + ' requires account_ref parameter to withdraw ' + code);
|
||||
throw new ArgumentsRequired (this.id + ' requires account_ref parameter to withdraw ' + code);
|
||||
}
|
||||
} else if (code !== 'LTC') {
|
||||
const tx_fee = ('tx_fee' in params);
|
||||
if (!tx_fee) {
|
||||
throw new ExchangeError (this.id + ' requires tx_fee parameter to withdraw ' + code);
|
||||
throw new ArgumentsRequired (this.id + ' requires tx_fee parameter to withdraw ' + code);
|
||||
}
|
||||
if (code === 'XRP') {
|
||||
if (tag === undefined) {
|
||||
if (!('destination_tag' in params)) {
|
||||
throw new ExchangeError (this.id + ' requires a tag argument or destination_tag parameter to withdraw ' + code);
|
||||
throw new ArgumentsRequired (this.id + ' requires a tag argument or destination_tag parameter to withdraw ' + code);
|
||||
}
|
||||
} else {
|
||||
request['destination_tag'] = tag;
|
||||
|
||||
+27
-40
@@ -3,7 +3,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const Exchange = require ('./base/Exchange');
|
||||
const { ExchangeError, ExchangeNotAvailable, ArgumentsRequired, BadRequest, AccountSuspended, InvalidAddress, PermissionDenied, DDoSProtection, InsufficientFunds, InvalidNonce, CancelPending, InvalidOrder, OrderNotFound, AuthenticationError, RequestTimeout, NotSupported, BadSymbol } = require ('./base/errors');
|
||||
const { ExchangeError, ExchangeNotAvailable, OnMaintenance, ArgumentsRequired, BadRequest, AccountSuspended, InvalidAddress, PermissionDenied, DDoSProtection, InsufficientFunds, InvalidNonce, CancelPending, InvalidOrder, OrderNotFound, AuthenticationError, RequestTimeout, NotSupported, BadSymbol } = require ('./base/errors');
|
||||
const { TICK_SIZE, TRUNCATE } = require ('./base/functions/number');
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -61,6 +61,9 @@ module.exports = class okex extends Exchange {
|
||||
'doc': 'https://www.okex.com/docs/en/',
|
||||
'fees': 'https://www.okex.com/pages/products/fees.html',
|
||||
'referral': 'https://www.okex.com/join/1888677',
|
||||
'test': {
|
||||
'rest': 'https://testnet.okex.com',
|
||||
},
|
||||
},
|
||||
'api': {
|
||||
'general': {
|
||||
@@ -348,8 +351,9 @@ module.exports = class okex extends Exchange {
|
||||
'30034': ExchangeError, // { "code": 30034, "message": "exchange ID does not exist" }
|
||||
'30035': ExchangeError, // { "code": 30035, "message": "trading is not supported in this website" }
|
||||
'30036': ExchangeError, // { "code": 30036, "message": "no relevant data" }
|
||||
'30038': AuthenticationError, // { "code": 30038, "message": "user does not exist" }
|
||||
'30037': ExchangeNotAvailable, // { "code": 30037, "message": "endpoint is offline or unavailable" }
|
||||
// '30038': AuthenticationError, // { "code": 30038, "message": "user does not exist" }
|
||||
'30038': OnMaintenance, // {"client_oid":"","code":"30038","error_code":"30038","error_message":"Matching engine is being upgraded. Please try in about 1 minute.","message":"Matching engine is being upgraded. Please try in about 1 minute.","order_id":"-1","result":false}
|
||||
// futures
|
||||
'32001': AccountSuspended, // { "code": 32001, "message": "futures account suspended" }
|
||||
'32002': PermissionDenied, // { "code": 32002, "message": "futures account does not exist" }
|
||||
@@ -792,14 +796,6 @@ module.exports = class okex extends Exchange {
|
||||
'price': this.safeFloat (market, 'tick_size'),
|
||||
};
|
||||
const minAmount = this.safeFloat2 (market, 'min_size', 'base_min_size');
|
||||
let minPrice = this.safeFloat (market, 'tick_size');
|
||||
if (precision['price'] !== undefined) {
|
||||
minPrice = Math.pow (10, -precision['price']);
|
||||
}
|
||||
let minCost = undefined;
|
||||
if (minAmount !== undefined && minPrice !== undefined) {
|
||||
minCost = minAmount * minPrice;
|
||||
}
|
||||
const active = true;
|
||||
const fees = this.safeValue2 (this.fees, marketType, 'trading', {});
|
||||
return this.extend (fees, {
|
||||
@@ -823,11 +819,11 @@ module.exports = class okex extends Exchange {
|
||||
'max': undefined,
|
||||
},
|
||||
'price': {
|
||||
'min': minPrice,
|
||||
'min': precision['price'],
|
||||
'max': undefined,
|
||||
},
|
||||
'cost': {
|
||||
'min': minCost,
|
||||
'min': precision['price'],
|
||||
'max': undefined,
|
||||
},
|
||||
},
|
||||
@@ -1360,8 +1356,18 @@ module.exports = class okex extends Exchange {
|
||||
'instrument_id': market['id'],
|
||||
'granularity': this.timeframes[timeframe],
|
||||
};
|
||||
const duration = this.parseTimeframe (timeframe);
|
||||
if (since !== undefined) {
|
||||
if (limit !== undefined) {
|
||||
request['end'] = this.iso8601 (this.sum (since, limit * duration * 1000));
|
||||
}
|
||||
request['start'] = this.iso8601 (since);
|
||||
} else {
|
||||
const now = this.milliseconds ();
|
||||
if (limit !== undefined) {
|
||||
request['start'] = this.iso8601 (now - limit * duration * 1000);
|
||||
request['end'] = this.iso8601 (now);
|
||||
}
|
||||
}
|
||||
const response = await this[method] (this.extend (request, params));
|
||||
//
|
||||
@@ -1841,28 +1847,7 @@ module.exports = class okex extends Exchange {
|
||||
// "result":true
|
||||
// }
|
||||
//
|
||||
const timestamp = this.milliseconds ();
|
||||
const id = this.safeString (response, 'order_id');
|
||||
return {
|
||||
'info': response,
|
||||
'id': id,
|
||||
'timestamp': timestamp,
|
||||
'datetime': this.iso8601 (timestamp),
|
||||
'lastTradeTimestamp': undefined,
|
||||
'status': undefined,
|
||||
'symbol': symbol,
|
||||
'type': type,
|
||||
'side': side,
|
||||
'price': price,
|
||||
'amount': amount,
|
||||
'filled': undefined,
|
||||
'remaining': undefined,
|
||||
'cost': undefined,
|
||||
'trades': undefined,
|
||||
'fee': undefined,
|
||||
'clientOrderId': undefined,
|
||||
'average': undefined,
|
||||
};
|
||||
return this.parseOrder (response, market);
|
||||
}
|
||||
|
||||
async cancelOrder (id, symbol = undefined, params = {}) {
|
||||
@@ -2302,9 +2287,11 @@ module.exports = class okex extends Exchange {
|
||||
}
|
||||
|
||||
parseDepositAddresses (addresses) {
|
||||
const result = [];
|
||||
const result = {};
|
||||
for (let i = 0; i < addresses.length; i++) {
|
||||
result.push (this.parseDepositAddress (addresses[i]));
|
||||
const address = this.parseDepositAddress (addresses[i]);
|
||||
const code = address['currency'];
|
||||
result[code] = address;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -2350,11 +2337,11 @@ module.exports = class okex extends Exchange {
|
||||
// ]
|
||||
//
|
||||
const addresses = this.parseDepositAddresses (response);
|
||||
const numAddresses = addresses.length;
|
||||
if (numAddresses < 1) {
|
||||
const address = this.safeValue (addresses, code);
|
||||
if (address === undefined) {
|
||||
throw new InvalidAddress (this.id + ' fetchDepositAddress cannot return nonexistent addresses, you should create withdrawal addresses with the exchange website first');
|
||||
}
|
||||
return addresses[0];
|
||||
return address;
|
||||
}
|
||||
|
||||
async withdraw (code, amount, address, tag = undefined, params = {}) {
|
||||
@@ -2366,7 +2353,7 @@ module.exports = class okex extends Exchange {
|
||||
}
|
||||
const fee = this.safeString (params, 'fee');
|
||||
if (fee === undefined) {
|
||||
throw new ExchangeError (this.id + " withdraw() requires a `fee` string parameter, network transaction fee must be ≥ 0. Withdrawals to OKCoin or OKEx are fee-free, please set '0'. Withdrawing to external digital asset address requires network transaction fee.");
|
||||
throw new ArgumentsRequired (this.id + " withdraw() requires a `fee` string parameter, network transaction fee must be ≥ 0. Withdrawals to OKCoin or OKEx are fee-free, please set '0'. Withdrawing to external digital asset address requires network transaction fee.");
|
||||
}
|
||||
const request = {
|
||||
'currency': currency['id'],
|
||||
|
||||
+18
-11
@@ -27,6 +27,7 @@ module.exports = class paymium extends Exchange {
|
||||
'https://github.com/Paymium/api-documentation',
|
||||
'https://www.paymium.com/page/developers',
|
||||
],
|
||||
'referral': 'https://www.paymium.com/page/sign-up?referral=eDAzPoRQFMvaAB8sf-qj',
|
||||
},
|
||||
'api': {
|
||||
'public': {
|
||||
@@ -41,12 +42,12 @@ module.exports = class paymium extends Exchange {
|
||||
},
|
||||
'private': {
|
||||
'get': [
|
||||
'merchant/get_payment/{UUID}',
|
||||
'merchant/get_payment/{uuid}',
|
||||
'user',
|
||||
'user/addresses',
|
||||
'user/addresses/{btc_address}',
|
||||
'user/orders',
|
||||
'user/orders/{UUID}',
|
||||
'user/orders/{uuid}',
|
||||
'user/price_alerts',
|
||||
],
|
||||
'post': [
|
||||
@@ -57,7 +58,7 @@ module.exports = class paymium extends Exchange {
|
||||
'merchant/create_payment',
|
||||
],
|
||||
'delete': [
|
||||
'user/orders/{UUID}/cancel',
|
||||
'user/orders/{uuid}/cancel',
|
||||
'user/price_alerts/{id}',
|
||||
],
|
||||
},
|
||||
@@ -204,9 +205,9 @@ module.exports = class paymium extends Exchange {
|
||||
|
||||
async cancelOrder (id, symbol = undefined, params = {}) {
|
||||
const request = {
|
||||
'UUID': id,
|
||||
'uuid': id,
|
||||
};
|
||||
return await this.privateDeleteUserOrdersUUIDCancel (this.extend (request, params));
|
||||
return await this.privateDeleteUserOrdersUuidCancel (this.extend (request, params));
|
||||
}
|
||||
|
||||
sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
|
||||
@@ -220,18 +221,24 @@ module.exports = class paymium extends Exchange {
|
||||
this.checkRequiredCredentials ();
|
||||
const nonce = this.nonce ().toString ();
|
||||
let auth = nonce + url;
|
||||
headers = {
|
||||
'Api-Key': this.apiKey,
|
||||
'Api-Nonce': nonce,
|
||||
};
|
||||
if (method === 'POST') {
|
||||
if (Object.keys (query).length) {
|
||||
body = this.json (query);
|
||||
auth += body;
|
||||
headers['Content-Type'] = 'application/json';
|
||||
}
|
||||
} else {
|
||||
if (Object.keys (query).length) {
|
||||
const queryString = this.urlencode (query);
|
||||
auth += queryString;
|
||||
url += '?' + queryString;
|
||||
}
|
||||
}
|
||||
headers = {
|
||||
'Api-Key': this.apiKey,
|
||||
'Api-Signature': this.hmac (this.encode (auth), this.encode (this.secret)),
|
||||
'Api-Nonce': nonce,
|
||||
'Content-Type': 'application/json',
|
||||
};
|
||||
headers['Api-Signature'] = this.hmac (this.encode (auth), this.encode (this.secret));
|
||||
}
|
||||
return { 'url': url, 'method': method, 'body': body, 'headers': headers };
|
||||
}
|
||||
|
||||
+2
-1
@@ -3,7 +3,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const Exchange = require ('./base/Exchange');
|
||||
const { ExchangeError, ExchangeNotAvailable, RequestTimeout, AuthenticationError, PermissionDenied, DDoSProtection, InsufficientFunds, OrderNotFound, OrderNotCached, InvalidOrder, AccountSuspended, CancelPending, InvalidNonce } = require ('./base/errors');
|
||||
const { ExchangeError, ExchangeNotAvailable, RequestTimeout, AuthenticationError, PermissionDenied, DDoSProtection, InsufficientFunds, OrderNotFound, OrderNotCached, InvalidOrder, AccountSuspended, CancelPending, InvalidNonce, OnMaintenance } = require ('./base/errors');
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -170,6 +170,7 @@ module.exports = class poloniex extends Exchange {
|
||||
'Permission denied': PermissionDenied,
|
||||
'Connection timed out. Please try again.': RequestTimeout,
|
||||
'Internal error. Please try again.': ExchangeNotAvailable,
|
||||
'Currently in maintenance mode.': OnMaintenance,
|
||||
'Order not found, or you are not the person who placed it.': OrderNotFound,
|
||||
'Invalid API key/secret pair.': AuthenticationError,
|
||||
'Please do not make more than 8 API calls per second.': DDoSProtection,
|
||||
|
||||
-1
@@ -17,7 +17,6 @@ module.exports = async (exchange, symbol) => {
|
||||
'btcalpha', // issue with 404 on a documented endpoint https://travis-ci.org/ccxt/ccxt/builds/643930431#L2213
|
||||
'bitmex', // an issue with null values,to be resolved later
|
||||
'cex',
|
||||
'mandala',
|
||||
]
|
||||
|
||||
if (skippedExchanges.includes (exchange.id)) {
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ const log = require ('ololog')
|
||||
|
||||
module.exports = async (exchange) => {
|
||||
|
||||
const randomSymbols = exchange.symbols.sort (() => 0.5 - Math.random ()).slice (0, 2)
|
||||
const randomSymbols = exchange.symbols.slice ().sort (() => 0.5 - Math.random ()).slice (0, 2)
|
||||
const customExchangeParams = ([
|
||||
'yobit',
|
||||
'tidex',
|
||||
|
||||
-1
@@ -14,7 +14,6 @@ const log = require ('ololog')
|
||||
module.exports = async (exchange, symbol) => {
|
||||
|
||||
const skippedExchanges = [
|
||||
'mandala',
|
||||
'rightbtc',
|
||||
]
|
||||
|
||||
|
||||
-1
@@ -76,7 +76,6 @@ module.exports = (exchange, ticker, method, symbol) => {
|
||||
'xbtce',
|
||||
'coss',
|
||||
'idex',
|
||||
'mandala',
|
||||
'mercado',
|
||||
'okex',
|
||||
'southxchange', // https://user-images.githubusercontent.com/1294454/59953532-314bea80-9489-11e9-85b3-2a711ca49aa7.png
|
||||
|
||||
+5
@@ -25,6 +25,8 @@ assert (toWei ('0.001', 18) === '1000000000000000');
|
||||
assert (toWei (0.1, 18) === '100000000000000000');
|
||||
assert (toWei (0.01, 18) === '10000000000000000');
|
||||
assert (toWei (0.001, 18) === '1000000000000000');
|
||||
assert (toWei ('0.3323340739', 18) === '332334073900000000');
|
||||
assert (toWei (0.3323340739, 18) === '332334073900000000');
|
||||
|
||||
// let us test that we get the inverse for all these test
|
||||
assert (fromWei ('1000000000000000000', 18) === 1.0);
|
||||
@@ -43,6 +45,8 @@ assert (fromWei ('1000000000000000', 18) === 0.001);
|
||||
assert (fromWei (100000000000000000, 18) === 0.1);
|
||||
assert (fromWei (10000000000000000, 18) === 0.01);
|
||||
assert (fromWei (1000000000000000, 18) === 0.001);
|
||||
assert (fromWei ('332334073900000000', 18) === 0.3323340739);
|
||||
assert (fromWei (332334073900000000, 18) === 0.3323340739);
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// numberToString
|
||||
@@ -58,6 +62,7 @@ assert (numberToString (7.9e27) === '7900000000000000000000000000');
|
||||
assert (numberToString (-12.345) === '-12.345');
|
||||
assert (numberToString (12.345) === '12.345');
|
||||
assert (numberToString (0) === '0');
|
||||
assert (numberToString (7.35946e21) === '7359460000000000000000');
|
||||
// the following line breaks the test
|
||||
// see https://github.com/ccxt/ccxt/issues/5744
|
||||
// assert (numberToString (0.00000001) === '0.00000001');
|
||||
|
||||
+3
@@ -370,9 +370,12 @@ let tryAllProxies = async function (exchange, proxies) {
|
||||
;(async function test () {
|
||||
|
||||
if (exchangeSymbol) {
|
||||
|
||||
await loadExchange (exchange)
|
||||
await testSymbol (exchange, exchangeSymbol)
|
||||
|
||||
} else {
|
||||
|
||||
await tryAllProxies (exchange, proxies)
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -180,6 +180,9 @@ module.exports = class theocean extends Exchange {
|
||||
}
|
||||
|
||||
async fetchOHLCV (symbol, timeframe = '5m', since = undefined, limit = undefined, params = {}) {
|
||||
if (since === undefined) {
|
||||
throw new ArgumentsRequired (this.id + ' fetchOHLCV requires a since argument');
|
||||
}
|
||||
await this.loadMarkets ();
|
||||
const market = this.market (symbol);
|
||||
const request = {
|
||||
@@ -187,9 +190,6 @@ module.exports = class theocean extends Exchange {
|
||||
'quoteTokenAddress': market['quoteId'],
|
||||
'interval': this.timeframes[timeframe],
|
||||
};
|
||||
if (since === undefined) {
|
||||
throw new ExchangeError (this.id + ' fetchOHLCV requires a since argument');
|
||||
}
|
||||
since = parseInt (since);
|
||||
request['startTime'] = since;
|
||||
const response = await this.publicGetCandlesticks (this.extend (request, params));
|
||||
|
||||
+2
-2
@@ -3,7 +3,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const Exchange = require ('./base/Exchange');
|
||||
const { ExchangeError, InsufficientFunds, OrderNotFound } = require ('./base/errors');
|
||||
const { ExchangeError, InsufficientFunds, OrderNotFound, ArgumentsRequired } = require ('./base/errors');
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -460,7 +460,7 @@ module.exports = class tidebit extends Exchange {
|
||||
const currency = this.currency (code);
|
||||
const id = this.safeString (params, 'id');
|
||||
if (id === undefined) {
|
||||
throw new ExchangeError (this.id + ' withdraw() requires an extra `id` param (withdraw account id according to withdraws/bind_account_list endpoint');
|
||||
throw new ArgumentsRequired (this.id + ' withdraw() requires an extra `id` param (withdraw account id according to withdraws/bind_account_list endpoint');
|
||||
}
|
||||
const request = {
|
||||
'id': id,
|
||||
|
||||
+30
-13
@@ -42,6 +42,7 @@ module.exports = class timex extends Exchange {
|
||||
'api': 'https://plasma-relay-backend.timex.io',
|
||||
'www': 'https://timex.io',
|
||||
'doc': 'https://docs.timex.io',
|
||||
'referral': 'https://timex.io/?refcode=1x27vNkTbP1uwkCck',
|
||||
},
|
||||
'api': {
|
||||
'custody': {
|
||||
@@ -892,7 +893,21 @@ module.exports = class timex extends Exchange {
|
||||
// "active": true,
|
||||
// "withdrawalFee": "50000000000000000",
|
||||
// "purchaseCommissions": []
|
||||
// },
|
||||
// }
|
||||
//
|
||||
// https://github.com/ccxt/ccxt/issues/6878
|
||||
//
|
||||
// {
|
||||
// "symbol":"XRP",
|
||||
// "name":"Ripple",
|
||||
// "address":"0x0dc8882914f3ddeebf4cec6dc20edb99df3def6c",
|
||||
// "decimals":6,
|
||||
// "tradeDecimals":16,
|
||||
// "depositEnabled":true,
|
||||
// "withdrawalEnabled":true,
|
||||
// "transferEnabled":true,
|
||||
// "active":true
|
||||
// }
|
||||
//
|
||||
const id = this.safeString (currency, 'symbol');
|
||||
const code = this.safeCurrencyCode (id);
|
||||
@@ -901,20 +916,22 @@ module.exports = class timex extends Exchange {
|
||||
const active = this.safeValue (currency, 'active');
|
||||
// const fee = this.safeFloat (currency, 'withdrawalFee');
|
||||
const feeString = this.safeString (currency, 'withdrawalFee');
|
||||
const feeStringLen = feeString.length;
|
||||
const tradeDecimals = this.safeInteger (currency, 'tradeDecimals');
|
||||
let fee = undefined;
|
||||
const dotIndex = feeStringLen - tradeDecimals;
|
||||
if (dotIndex > 0) {
|
||||
const whole = feeString.slice (0, dotIndex);
|
||||
const fraction = feeString.slice (-dotIndex);
|
||||
fee = parseFloat (whole + '.' + fraction);
|
||||
} else {
|
||||
let fraction = '.';
|
||||
for (let i = 0; i < -dotIndex; i++) {
|
||||
fraction += '0';
|
||||
if ((feeString !== undefined) && (tradeDecimals !== undefined)) {
|
||||
const feeStringLen = feeString.length;
|
||||
const dotIndex = feeStringLen - tradeDecimals;
|
||||
if (dotIndex > 0) {
|
||||
const whole = feeString.slice (0, dotIndex);
|
||||
const fraction = feeString.slice (-dotIndex);
|
||||
fee = parseFloat (whole + '.' + fraction);
|
||||
} else {
|
||||
let fraction = '.';
|
||||
for (let i = 0; i < -dotIndex; i++) {
|
||||
fraction += '0';
|
||||
}
|
||||
fee = parseFloat (fraction + feeString);
|
||||
}
|
||||
fee = parseFloat (fraction + feeString);
|
||||
}
|
||||
return {
|
||||
'id': code,
|
||||
@@ -1105,7 +1122,7 @@ module.exports = class timex extends Exchange {
|
||||
this.safeFloat (ohlcv, 'high'),
|
||||
this.safeFloat (ohlcv, 'low'),
|
||||
this.safeFloat (ohlcv, 'close'),
|
||||
this.safeFloat (ohlcv, 'volumeQuote'),
|
||||
this.safeFloat (ohlcv, 'volume'),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -1324,9 +1324,11 @@ module.exports = class upbit extends Exchange {
|
||||
}
|
||||
|
||||
parseDepositAddresses (addresses) {
|
||||
const result = [];
|
||||
const result = {};
|
||||
for (let i = 0; i < addresses.length; i++) {
|
||||
result.push (this.parseDepositAddress (addresses[i]));
|
||||
const address = this.parseDepositAddress (addresses[i]);
|
||||
const code = address['currency'];
|
||||
result[code] = address;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
+2
-1
@@ -167,11 +167,12 @@ module.exports = class yobit extends Exchange {
|
||||
'api key dont have trade permission': AuthenticationError,
|
||||
'invalid parameter': InvalidOrder,
|
||||
'invalid order': InvalidOrder,
|
||||
'The given order has already been cancelled': InvalidOrder,
|
||||
'Requests too often': DDoSProtection,
|
||||
'not available': ExchangeNotAvailable,
|
||||
'data unavailable': ExchangeNotAvailable,
|
||||
'external service unavailable': ExchangeNotAvailable,
|
||||
'Total transaction amount': ExchangeError, // { "success": 0, "error": "Total transaction amount is less than minimal total: 0.00010000"}
|
||||
'Total transaction amount': InvalidOrder, // { "success": 0, "error": "Total transaction amount is less than minimal total: 0.00010000"}
|
||||
'Insufficient funds': InsufficientFunds,
|
||||
'invalid key': AuthenticationError,
|
||||
'invalid nonce': InvalidNonce, // {"success":0,"error":"invalid nonce (has already been used)"}'
|
||||
|
||||
Loaded 100 of 117 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user