Adding support for multiple bot execution

This commit is contained in:
mati108@gmail.com committed 2019-02-06 17:03:36 -03:00
1 parent 709a6cb770
commit 2cda4ad606
14 files changed
+74 -81

No files matched your search

+1 -1
View File
@@ -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": {
+1
View File
@@ -29,5 +29,6 @@ export const clone = gql`
botName
botAvatar
teamAvatar
processName
}
`;
+13 -16
View File
@@ -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 }
+11 -8
View File
@@ -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 => (
<MenuItem key={option} value={option}>
{option}
{tradingStartModes[option]}
</MenuItem>
))}
</TextField>
@@ -290,9 +290,9 @@ class AddClone extends Component {
error={this.state.modeError}
fullWidth
>
{startModes.map(option => (
<MenuItem key={option.value} value={option.value}>
{option.name}
{Object.keys(indicatorStartModes).map(option => (
<MenuItem key={option} value={option}>
{indicatorStartModes[option]}
</MenuItem>
))}
</TextField>
@@ -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({
+4 -1
View File
@@ -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 {
<Typography className={classes.heading}>{clone.botName}</Typography>
</div>
<div className={classes.heading}>
<Typography className={classes.heading}>{clone.mode}</Typography>
<Typography className={classes.heading}>
{ clone.processName } / { clone.botType === 'TRADER' ? tradingStartModes[clone.mode] : indicatorStartModes[clone.mode] }
</Typography>
</div>
</ExpansionPanelSummary>
<Divider />
+3 -3
View File
@@ -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'
+29 -30
View File
@@ -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
+2 -2
View File
@@ -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
}
}
+5 -1
View File
@@ -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)
-2
View File
@@ -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
@@ -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)
+3 -2
View File
@@ -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
}
+1
View File
@@ -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},
+1 -1
View File
@@ -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) }
})
});