diff --git a/client/package.json b/client/package.json index a3f97354c..9081461b8 100644 --- a/client/package.json +++ b/client/package.json @@ -1,6 +1,6 @@ { "name": "@superalgos/operations-client", - "version": "0.0.11", + "version": "0.0.12", "description": "Superalgos Operations client-side web app", "main": "src/index.js", "dependencies": { diff --git a/client/src/GraphQL/Fragments/clone.js b/client/src/GraphQL/Fragments/clone.js index 26a5aab59..42022c0bd 100644 --- a/client/src/GraphQL/Fragments/clone.js +++ b/client/src/GraphQL/Fragments/clone.js @@ -29,5 +29,6 @@ export const clone = gql` botName botAvatar teamAvatar + processName } `; diff --git a/client/src/GraphQL/models.js b/client/src/GraphQL/models.js index 50dd8a322..c7a5df51b 100644 --- a/client/src/GraphQL/models.js +++ b/client/src/GraphQL/models.js @@ -1,21 +1,18 @@ -const types = [ 'Live', 'Competition', 'Backtest' ] const availableMonths = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"] -const startModes = [ - { - name: 'All Months', - value: 'allMonths' - }, - { - name: 'One Month', - value: 'oneMonth' - }, - { - name: 'No Time', - value: 'noTime' - } -] +const tradingStartModes ={ + live: "Live", + competition: "Competition", + backtest: "Backtest" +} + +const indicatorStartModes = { + allMonths: "All Months", + oneMonth: "One Month", + noTime: "No Time" +} + const exchanges = [ { id: '1', @@ -25,4 +22,4 @@ const exchanges = [ -export { types, exchanges, startModes, availableMonths } +export { tradingStartModes, exchanges, indicatorStartModes, availableMonths } diff --git a/client/src/views/Clone/Add/index.js b/client/src/views/Clone/Add/index.js index 0a90f3fcb..3c03a4fb5 100644 --- a/client/src/views/Clone/Add/index.js +++ b/client/src/views/Clone/Add/index.js @@ -9,7 +9,7 @@ import { withStyles } from '@material-ui/core/styles' import classNames from 'classnames' import styles from './styles' -import { types, startModes, availableMonths, processNames } from '../../../GraphQL/models' +import { tradingStartModes, indicatorStartModes, availableMonths, processNames } from '../../../GraphQL/models' import { isDefined, getIndicatorYears } from '../../../utils' import { @@ -176,9 +176,9 @@ class AddClone extends Component { error={this.state.modeError} fullWidth > - {types.map(option => ( + {Object.keys(tradingStartModes).map(option => ( - {option} + {tradingStartModes[option]} ))} @@ -290,9 +290,9 @@ class AddClone extends Component { error={this.state.modeError} fullWidth > - {startModes.map(option => ( - - {option.name} + {Object.keys(indicatorStartModes).map(option => ( + + {indicatorStartModes[option]} ))} @@ -449,7 +449,6 @@ class AddClone extends Component { botId: this.state.selectedBot.id, mode: this.state.mode, resumeExecution: this.state.resumeExecution, - runAsTeam: this.state.runAsTeam, botType: this.getBotTypeFromKind(this.state.selectedBot.kind) } } @@ -460,11 +459,15 @@ class AddClone extends Component { variables.clone.waitTime = this.state.waitTime } - if(this.state.selectedBot.kind !== "TRADER"){ + if(this.state.selectedBot.kind === "TRADER"){ + variables.clone.runAsTeam = this.state.runAsTeam + variables.clone.processName = 'Trading-Process' + } else { variables.clone.processName = this.state.processName variables.clone.startYear = this.state.startYear variables.clone.endYear = this.state.endYear variables.clone.month = this.state.month + variables.clone.runAsTeam = true } return this.props.addCloneMutation({ diff --git a/client/src/views/Clone/List/ListClones.js b/client/src/views/Clone/List/ListClones.js index a939f8fbd..7eea28c18 100644 --- a/client/src/views/Clone/List/ListClones.js +++ b/client/src/views/Clone/List/ListClones.js @@ -14,6 +14,7 @@ import { import Avatar from '@material-ui/core/Avatar'; import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; +import { tradingStartModes, indicatorStartModes } from '../../../GraphQL/models' import { isDefined, toLocalTime } from '../../../utils' import classNames from 'classnames' import { withStyles } from '@material-ui/core/styles' @@ -45,7 +46,9 @@ class ListClones extends Component { {clone.botName} - {clone.mode} + + { clone.processName } / { clone.botType === 'TRADER' ? tradingStartModes[clone.mode] : indicatorStartModes[clone.mode] } + diff --git a/server/src/enums/CloneMode.js b/server/src/enums/CloneMode.js index 2a3109f26..0a463100f 100644 --- a/server/src/enums/CloneMode.js +++ b/server/src/enums/CloneMode.js @@ -1,6 +1,6 @@ -export const LIVE = 'Live' -export const BACKTEST = 'Backtest' -export const COMPETITION = 'Competition' +export const LIVE = 'live' +export const BACKTEST = 'backtest' +export const COMPETITION = 'competition' export const ALL_MONTHS = 'allMonths' export const ONE_MONTH = 'oneMonth' export const NO_TIME = 'noTime' diff --git a/server/src/kubernetes/createClone.js b/server/src/kubernetes/createClone.js index d71856faf..6565b6368 100644 --- a/server/src/kubernetes/createClone.js +++ b/server/src/kubernetes/createClone.js @@ -4,15 +4,16 @@ import { KubernateError } from '../errors' import { Client, config } from 'kubernetes-client' // Get base Deployment config import deploymentManifest from '../config/clone-deployment.json' -import { BACKTEST} from '../enums/CloneMode'; +import { BACKTEST, NO_TIME } from '../enums/CloneMode' +import { TRADER, INDICATOR, EXTRACTION } from '../enums/BotTypes' const createClone = async (clone) => { try { - logger.debug("createClone %s", clone.cloneName) + logger.debug("createClone %s", clone.id) const client = new Client({config: config.fromKubeconfig(), version: '1.9'}) // Make changes to base deployment config - deploymentManifest.metadata.name = clone.cloneName + deploymentManifest.metadata.name = clone.id logger.debug("createClone Environment and Auth Configuration.") let env = [] @@ -68,7 +69,7 @@ const createClone = async (clone) => { }) env.push({ "name": "START_MODE", - "value": clone.mode.toLowerCase() + "value": clone.mode }) env.push({ "name": "RUN_AS_TEAM", @@ -78,13 +79,13 @@ const createClone = async (clone) => { "name": "USER_LOGGED_IN", "value": clone.userLoggedIn }) + env.push({ + "name": "PROCESS", + "value": clone.processName + }) logger.debug("createClone Trading Configuration.") - if(clone.botType === 'Trading'){ - env.push({ - "name": "PROCESS", - "value": 'Trading-Process' - }) + if(clone.botType === TRADER ){ env.push({ "name": "RESUME_EXECUTION", "value": clone.resumeExecution.toString() @@ -104,27 +105,25 @@ const createClone = async (clone) => { "value": clone.waitTime.toString() }) } - } else if(clone.botType === 'Indicator' || clone.botType === 'Extraction'){ - env.push({ - "name": "PROCESS", - "value": clone.processName - }) - env.push({ - "name": "MIN_YEAR", - "value": isDefined(clone.startYear) ? clone.startYear.toString() : '' - }) - env.push({ - "name": "MAX_YEAR", - "value": isDefined(clone.endYear) ? clone.endYear.toString() : '' - }) - env.push({ - "name": "MONTH", - "value": isDefined(clone.month) ? clone.month.toString() : '' - }) - env.push({ - "name": "INTERVAL", - "value": isDefined(clone.interval) ? clone.interval.toString() : '' - }) + } else if(clone.botType === INDICATOR || clone.botType === EXTRACTION ){ + if(clone.mode !== NO_TIME){ + env.push({ + "name": "MIN_YEAR", + "value": isDefined(clone.startYear) ? clone.startYear.toString() : '' + }) + env.push({ + "name": "MAX_YEAR", + "value": isDefined(clone.endYear) ? clone.endYear.toString() : '' + }) + env.push({ + "name": "MONTH", + "value": isDefined(clone.month) ? clone.month.toString() : '' + }) + env.push({ + "name": "INTERVAL", + "value": isDefined(clone.interval) ? clone.interval.toString() : '' + }) + } } deploymentManifest.spec.template.spec.containers[0].env = env diff --git a/server/src/kubernetes/removeClone.js b/server/src/kubernetes/removeClone.js index dc6f2e10f..e6c908c10 100644 --- a/server/src/kubernetes/removeClone.js +++ b/server/src/kubernetes/removeClone.js @@ -4,12 +4,12 @@ import { Client, config } from 'kubernetes-client' const removeClone = async (clone) => { try { - logger.debug("removeClone %s", clone.cloneName) + logger.debug("removeClone %s", clone.id) const client = new Client({config: config.fromKubeconfig(), version: '1.9'}) let query = { "qs":{ - "labelSelector": "job-name=" + clone.cloneName + "labelSelector": "job-name=" + clone.id } } diff --git a/server/src/models/clone.js b/server/src/models/clone.js index 45532d5b9..e69df8262 100644 --- a/server/src/models/clone.js +++ b/server/src/models/clone.js @@ -48,7 +48,11 @@ const cloneSchema = new Schema({ combinedProfitsA: Number, combinedProfitsB: Number, assetA: String, - assetB: String + assetB: String, + processName: { + type: String, + required: true, + } }) const Clone = mongoose.model('Clone', cloneSchema) diff --git a/server/src/schema/cloneDetails.js b/server/src/schema/cloneDetails.js index 74849e583..08cee99be 100644 --- a/server/src/schema/cloneDetails.js +++ b/server/src/schema/cloneDetails.js @@ -5,7 +5,6 @@ import { AutorizationError } from '../errors' const cloneDetails = async(authId, team, clone) => { logger.debug('Retrieving clone details.') - // TODO Pending improvement by authorization module if(!(authId === process.env.AACLOUD_ID || isAuthorized(team, authId))){ logger.debug('User %s is not authorized to manage team %s.', authId, team.slug ) throw new AutorizationError() @@ -17,7 +16,6 @@ const cloneDetails = async(authId, team, clone) => { clone.kind = selectedBot.kind clone.teamSlug = team.slug clone.botSlug = selectedBot.slug - clone.cloneName = (clone.teamSlug + '-' + clone.botSlug + '-' + clone.mode).toLowerCase() clone.teamName = team.name clone.botName = selectedBot.name clone.botAvatar = selectedBot.avatar diff --git a/server/src/schema/mutations/AddCloneMutation.js b/server/src/schema/mutations/AddCloneMutation.js index c9ca557a1..a0f9db02e 100644 --- a/server/src/schema/mutations/AddCloneMutation.js +++ b/server/src/schema/mutations/AddCloneMutation.js @@ -35,20 +35,6 @@ const resolve = async(parent, { clone }, context) => { throw new WrongArgumentsError('The bot type selected is not valid.') } - let existingClone = await Clone.find( - { - authId: context.userId, - mode: clone.mode, - botId: clone.botId, - active: true - }) - - logger.debug('addClone -> Checking existing clone.') - if(existingClone.length > 0){ - throw new OperationsError('You can only have one active clone by mode. Remove the' - + ' existing clone of type: ' + clone.mode + ' and try again.') - } - try{ let team = await teamQuery(context.authorization, clone.teamId) clone = await cloneDetails(context.userId, team.data.data.teams_TeamById, clone) diff --git a/server/src/schema/queries/ListClones.js b/server/src/schema/queries/ListClones.js index 48dd48a00..0d15db13e 100644 --- a/server/src/schema/queries/ListClones.js +++ b/server/src/schema/queries/ListClones.js @@ -30,11 +30,12 @@ const resolve = async(parent, args, context) => { }).sort({createDatetime: -1}) for (var i = 0; i < clones.length; i++) { + logger.debug('List Clones -> clone: %j',clones[i] ) let team = await teamQuery(context.authorization, clones[i].teamId) clones[i] = await cloneDetails(context.userId, team.data.data.teams_TeamById, clones[i]) - let state = await getCloneStatus(clones[i].cloneName) + let state = await getCloneStatus(clones[i].id) clones[i].state = state.substring(1, state.length-1) - let lastLogs = await getCloneLogs(clones[i].cloneName) + let lastLogs = await getCloneLogs(clones[i].id) clones[i].lastLogs = lastLogs.substring(1, lastLogs.length-1) clones[i].botType = clones[i].kind // Only for listing we show the teams value } diff --git a/server/src/schema/types/CloneType.js b/server/src/schema/types/CloneType.js index 5a653c35e..dfcd10a68 100644 --- a/server/src/schema/types/CloneType.js +++ b/server/src/schema/types/CloneType.js @@ -24,6 +24,7 @@ const CloneType = new GraphQLObjectType({ createDatetime: {type: GraphQLInt}, lastLogs: {type: GraphQLString}, runAsTeam: {type: GraphQLBoolean}, + processName: { type: GraphQLString }, summaryDate: {type: GraphQLInt}, buyAverage: {type: GraphQLFloat}, sellAverage: {type: GraphQLFloat}, diff --git a/server/src/schema/types/input/Clone.js b/server/src/schema/types/input/Clone.js index 0db3cdf0d..a4a6d95ec 100644 --- a/server/src/schema/types/input/Clone.js +++ b/server/src/schema/types/input/Clone.js @@ -22,7 +22,7 @@ const Type = new GraphQLInputObjectType({ endYear: { type: GraphQLInt }, month: { type: GraphQLInt }, interval: { type: GraphQLInt }, - processName: { type: GraphQLString }, + processName: { type: new GraphQLNonNull(GraphQLString) }, botType: { type: new GraphQLNonNull(GraphQLString) } }) });