diff --git a/client/package-lock.json b/client/package-lock.json
index a41a32819..60295d23c 100644
--- a/client/package-lock.json
+++ b/client/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "@superalgos/operations-client",
- "version": "0.0.17",
+ "version": "0.0.18",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/client/package.json b/client/package.json
index 63204e01c..483789cf3 100644
--- a/client/package.json
+++ b/client/package.json
@@ -1,6 +1,6 @@
{
"name": "@superalgos/operations-client",
- "version": "0.0.18",
+ "version": "0.0.21",
"description": "Superalgos Operations client-side web app",
"main": "src/index.js",
"dependencies": {
diff --git a/client/src/GraphQL/models.js b/client/src/GraphQL/models.js
index cd7e37973..0ce6667fc 100644
--- a/client/src/GraphQL/models.js
+++ b/client/src/GraphQL/models.js
@@ -1,5 +1,19 @@
-const availableMonths = ['January', 'February', 'March', 'April', 'May', 'June',
- 'July', 'August', 'September', 'October', 'November', 'December']
+const availableMonths = [
+ 'January',
+ 'February',
+ 'March',
+ 'April',
+ 'May',
+ 'June',
+ 'July',
+ 'August',
+ 'September',
+ 'October',
+ 'November',
+ 'December'
+]
+
+const availableTimePeriods = ["24-hs", "12-hs", "08-hs", "06-hs", "04-hs", "03-hs", "02-hs", "01-hs", "45-min", "40-min", "30-min", "20-min", "15-min", "10-min", "05-min", "04-min", "03-min", "02-min", "01-min"]
const tradingStartModes = {
live: 'Live',
@@ -18,6 +32,14 @@ const indicatorStartModes = {
noTime: 'No Time'
}
+const processNames = {
+ Daily: 'Multi-Period-Daily',
+ Market: 'Multi-Period-Market',
+ Min: "One-Min-Daily-Candles-Volumes",
+ Live: "Poloniex-Live-Trades",
+ HoleFixing: "Poloniex-Hole-Fixing"
+}
+
const exchanges = [
{
id: '1',
@@ -25,4 +47,4 @@ const exchanges = [
}
]
-export { tradingStartModes, tradingStartModesList, exchanges, indicatorStartModes, availableMonths }
+export { tradingStartModes, tradingStartModesList, exchanges, indicatorStartModes, availableMonths, processNames, availableTimePeriods }
diff --git a/client/src/views/Clone/Add/index.js b/client/src/views/Clone/Add/index.js
index 4e52af534..dce62039f 100644
--- a/client/src/views/Clone/Add/index.js
+++ b/client/src/views/Clone/Add/index.js
@@ -6,7 +6,7 @@ import TopBar from '../../BannerTopBar'
import { withStyles } from '@material-ui/core/styles'
import classNames from 'classnames'
import styles from './styles'
-import { tradingStartModes, indicatorStartModes, availableMonths } from '../../../GraphQL/models'
+import { tradingStartModes, indicatorStartModes, availableMonths, processNames, availableTimePeriods } from '../../../GraphQL/models'
import { isDefined, getIndicatorYears } from '../../../utils'
import {
MenuItem, Button, TextField, FormControl, InputLabel, Input, Typography,
@@ -43,6 +43,9 @@ class AddClone extends Component {
month: 1,
processName: '',
+ //TraderBot
+ timePeriod: '01-hs',
+
//Error handlers
nameError: false,
teamError: false,
@@ -215,19 +218,6 @@ class AddClone extends Component {
className={classNames(classes.form, classes.textField)}
fullWidth
/>
-
-
- The Wait Time represent the number of miliseconds the bot will wait between executions.
-
-
- this.setState({waitTime:e.target.value})}
- fullWidth
- />
}
@@ -290,6 +280,27 @@ class AddClone extends Component {
}
+
+
+
+ The Time Period in which the bot will operate.
+
+
+ this.setState({timePeriod:e.target.value})}
+ fullWidth
+ >
+ {availableTimePeriods.map((option, index) => (
+
+ ))}
+
+
{ false &&
@@ -320,6 +331,7 @@ class AddClone extends Component {
|| this.state.selectedBot.kind === "EXTRACTOR") &&
this.setState({processNameError:false})}
error={this.state.processNameError}
fullWidth
- />
+ >
+ {Object.keys(processNames).map(option => (
+
+ ))}
+
+
{getIndicatorYears().map((option, index) => (
-
this.setState({month:e.target.value})}
fullWidth
>
- {availableMonths.map(option => (
-
+ {availableMonths.map((option, index) => (
+
{option}
))}
@@ -506,6 +525,7 @@ class AddClone extends Component {
if(this.state.selectedBot.kind === "TRADER"){
variables.clone.runAsTeam = this.state.runAsTeam
variables.clone.processName = 'Trading-Process'
+ variables.clone.timePeriod = this.state.timePeriod
if(this.state.mode === "backtest"){
variables.clone.beginDatetime = this.state.beginDatetime.valueOf() / 1000|0
variables.clone.endDatetime = this.state.endDatetime.valueOf() / 1000|0
diff --git a/server/src/kubernetes/createClone.js b/server/src/kubernetes/createClone.js
index 83ac6af4e..57d6560cf 100644
--- a/server/src/kubernetes/createClone.js
+++ b/server/src/kubernetes/createClone.js
@@ -88,6 +88,11 @@ const createClone = async (clone) => {
'value': clone.resumeExecution.toString()
})
+ env.push({
+ 'name': 'EXECUTION_PARAMETERS',
+ 'value': buildExecutionParameters(clone)
+ })
+
if (clone.mode === BACKTEST) {
env.push({
'name': 'BEGIN_DATE_TIME',
@@ -151,4 +156,36 @@ const createClone = async (clone) => {
throw new KubernateError(err)
}
}
+
+function buildExecutionParameters(clone){
+ let executionParameters = {}
+ executionParameters.timePeriod = clone.timePeriod
+ executionParameters.dataSet = datasetNames().get(clone.timePeriod)
+ return executionParameters
+}
+
+function datasetNames(){
+ let dataSetMap = new Map()
+ dataSetMap.set("24-hs","Multi-Period-Market")
+ dataSetMap.set("12-hs","Multi-Period-Market")
+ dataSetMap.set("08-hs","Multi-Period-Market")
+ dataSetMap.set("06-hs","Multi-Period-Market")
+ dataSetMap.set("04-hs","Multi-Period-Market")
+ dataSetMap.set("03-hs","Multi-Period-Market")
+ dataSetMap.set("02-hs","Multi-Period-Market")
+ dataSetMap.set("01-hs","Multi-Period-Market")
+ dataSetMap.set("45-min","Multi-Period-Daily")
+ dataSetMap.set("40-min","Multi-Period-Daily")
+ dataSetMap.set("30-min","Multi-Period-Daily")
+ dataSetMap.set("20-min","Multi-Period-Daily")
+ dataSetMap.set("15-min","Multi-Period-Daily")
+ dataSetMap.set("10-min","Multi-Period-Daily")
+ dataSetMap.set("05-min","Multi-Period-Daily")
+ dataSetMap.set("04-min","Multi-Period-Daily")
+ dataSetMap.set("03-min","Multi-Period-Daily")
+ dataSetMap.set("02-min","Multi-Period-Daily")
+ dataSetMap.set("01-min","Multi-Period-Daily")
+ return dataSetMap
+}
+
export default createClone
diff --git a/server/src/kubernetes/getClonePodLogs.js b/server/src/kubernetes/getClonePodLogs.js
index 5367bfdd8..52c97230a 100644
--- a/server/src/kubernetes/getClonePodLogs.js
+++ b/server/src/kubernetes/getClonePodLogs.js
@@ -20,13 +20,18 @@ const getClonePodLogs = async (cloneName) => {
'tailLines': '20'
}
}
- const logs = await client.api.v1.namespaces('default')
- .pods(pod.body.items[0].metadata.name).log.get(queryLogs)
- let logsArray = logs.body.split('\n')
+ if(pod.body.items[0] !== undefined){
+ const logs = await client.api.v1.namespaces('default')
+ .pods(pod.body.items[0].metadata.name).log.get(queryLogs)
+ let logsArray = logs.body.split('\n')
- logger.debug('getClonePodLogs on kubernates successful.')
+ logger.debug('getClonePodLogs on kubernates successful.')
- return JSON.stringify(logsArray, null, 2)
+ return JSON.stringify(logsArray, null, 2)
+ } else {
+ logger.warn('getClonePodStatus pod not found %s: ', cloneName)
+ return "Logs not available."
+ }
} catch (err) {
throw new KubernateError(err)
}
diff --git a/server/src/kubernetes/getClonePodStatus.js b/server/src/kubernetes/getClonePodStatus.js
index 957cf49ed..94412b09e 100644
--- a/server/src/kubernetes/getClonePodStatus.js
+++ b/server/src/kubernetes/getClonePodStatus.js
@@ -5,7 +5,7 @@ import { Client, config } from 'kubernetes-client'
const getClonePodStatus = async (cloneName) => {
try {
logger.debug('getClonePodStatus on kubernates started. ')
- const client = new Client({config: config.fromKubeconfig(), version: '1.9'})
+ const client = new Client({ config: config.fromKubeconfig(), version: '1.9' })
let query = {
'qs': {
@@ -15,14 +15,20 @@ const getClonePodStatus = async (cloneName) => {
const pod = await client.api.v1.namespaces('default').pods.get(query)
- let clonePodStatus = pod.body.items[0].status.containerStatuses[0].state
+ if (pod.body.items[0] !== undefined) {
+ let clonePodStatus = pod.body.items[0].status.containerStatuses[0].state
- if (clonePodStatus.hasOwnProperty('terminated')
- && clonePodStatus.terminated.hasOwnProperty('containerID')) {
- delete clonePodStatus.terminated.containerID
+ if (clonePodStatus.hasOwnProperty('terminated')
+ && clonePodStatus.terminated.hasOwnProperty('containerID')) {
+ delete clonePodStatus.terminated.containerID
+ }
+ logger.debug('getClonePodStatus %s on kubernates successful', cloneName)
+
+ return JSON.stringify(clonePodStatus, null, 2)
+ } else {
+ logger.warn('getClonePodStatus pod not found %s: ', cloneName)
+ return " Clone not found on the server. "
}
- logger.debug('getClonePodStatus %s on kubernates successful', cloneName)
- return JSON.stringify(clonePodStatus, null, 2)
} catch (err) {
throw new KubernateError(err)
}
diff --git a/server/src/kubernetes/removeClone.js b/server/src/kubernetes/removeClone.js
index 8bac6a3fa..54bb0c3c5 100644
--- a/server/src/kubernetes/removeClone.js
+++ b/server/src/kubernetes/removeClone.js
@@ -20,7 +20,7 @@ const removeClone = async (clone) => {
logger.debug('removeClone %s on kubernates succesful', clone.id)
} catch (err) {
- throw new KubernateError(err)
+ logger.warn('removeClone %s on kubernates failed, the job was not found on the server.', clone.id)
}
}
export default removeClone
diff --git a/server/src/schema/mutations/AddCloneMutation.js b/server/src/schema/mutations/AddCloneMutation.js
index 092ffe6e7..edaf47e4d 100644
--- a/server/src/schema/mutations/AddCloneMutation.js
+++ b/server/src/schema/mutations/AddCloneMutation.js
@@ -21,7 +21,7 @@ const args = {
clone: { type: CloneInputType }
}
-const resolve = async(parent, { clone }, context) => {
+const resolve = async (parent, { clone }, context) => {
logger.debug('addClone -> Entering Fuction.')
if (!context.userId) {
@@ -36,7 +36,7 @@ const resolve = async(parent, { clone }, context) => {
throw new WrongArgumentsError('The bot type selected is not valid.')
}
- if ( (clone.mode === LIVE || clone.mode === COMPETITION) && !isDefined(clone.keyId)) {
+ if ((clone.mode === LIVE || clone.mode === COMPETITION) && !isDefined(clone.keyId)) {
throw new WrongArgumentsError('The key was not provided to run the clone.')
}
@@ -62,7 +62,7 @@ const resolve = async(parent, { clone }, context) => {
} else {
throw new AutorizationError()
}
- }else{
+ } else {
await createKubernetesClone(clone)
}
diff --git a/server/src/schema/types/input/Clone.js b/server/src/schema/types/input/Clone.js
index 509ea9af5..3b106dafa 100644
--- a/server/src/schema/types/input/Clone.js
+++ b/server/src/schema/types/input/Clone.js
@@ -24,7 +24,8 @@ const Type = new GraphQLInputObjectType({
interval: { type: GraphQLInt },
processName: { type: new GraphQLNonNull(GraphQLString) },
botType: { type: new GraphQLNonNull(GraphQLString) },
- keyId: { type: GraphQLString }
+ keyId: { type: GraphQLString },
+ timePeriod: { type: GraphQLString }
})
})