Adding support for Indicators and Extractors
This commit is contained in:
1 parent
f942581f58
commit
a8ac7385d6
12 files changed
+325
-356
No files matched your search
Generated
+10
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@advancedalgos/operations-client",
|
||||
"version": "0.0.1",
|
||||
"name": "@superalgos/operations-client",
|
||||
"version": "0.0.2",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -689,6 +689,14 @@
|
||||
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
|
||||
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
|
||||
},
|
||||
"react-number-format": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/react-number-format/-/react-number-format-4.0.6.tgz",
|
||||
"integrity": "sha512-WfBlqYRD0fGZpQxRy1apxsPeaqtxhzo7CnUVFKBoGDsQbc89+DQNhjG/D3IxgGYM47oKB+W/Su9ol/vVS6Wc2Q==",
|
||||
"requires": {
|
||||
"prop-types": "15.6.2"
|
||||
}
|
||||
},
|
||||
"react-router": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-4.3.1.tgz",
|
||||
|
||||
+3
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@advancedalgos/operations-client",
|
||||
"version": "0.0.1",
|
||||
"name": "@superalgos/operations-client",
|
||||
"version": "0.0.2",
|
||||
"description": "Superalgos Operations client-side web app",
|
||||
"main": "src/index.js",
|
||||
"dependencies": {
|
||||
@@ -15,6 +15,7 @@
|
||||
"react": "^16.6.1",
|
||||
"react-apollo": "^2.2.4",
|
||||
"react-dom": "^16.6.1",
|
||||
"react-number-format": "^4.0.6",
|
||||
"react-router-dom": "^4.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -10,29 +10,12 @@ export const GET_ALL_TEAMS_QUERY = gql`
|
||||
id
|
||||
name
|
||||
slug
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
export const GET_ALL_TEAM_BOTS_QUERY = gql`
|
||||
query teamBotsQuery($teamId: String!) {
|
||||
teams_TeamById(teamId: $teamId) {
|
||||
fb {
|
||||
id
|
||||
name
|
||||
slug
|
||||
team{
|
||||
id
|
||||
name
|
||||
slug
|
||||
}
|
||||
kind
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
export default {
|
||||
GET_ALL_TEAMS_QUERY,
|
||||
GET_ALL_TEAM_BOTS_QUERY
|
||||
GET_ALL_TEAMS_QUERY
|
||||
};
|
||||
@@ -1,4 +1,7 @@
|
||||
const types = [ 'Live', 'Competition', 'Backtest' ]
|
||||
const startModes = [ 'All Months', 'One Month', 'No Time' ]
|
||||
const availableMonths = ["January", "February", "March", "April", "May", "June",
|
||||
"July", "August", "September", "October", "November", "December"]
|
||||
|
||||
const exchanges = [
|
||||
{
|
||||
@@ -7,4 +10,6 @@ const exchanges = [
|
||||
}
|
||||
]
|
||||
|
||||
export { types, exchanges }
|
||||
|
||||
|
||||
export { types, exchanges, startModes, availableMonths }
|
||||
@@ -72,3 +72,12 @@ export function slugify (string) {
|
||||
.replace(/^-+/, '') // Trim - from start of text
|
||||
.replace(/-+$/, '') // Trim - from end of text
|
||||
}
|
||||
|
||||
export function getIndicatorYears () {
|
||||
const localDate = new Date()
|
||||
let availableYears = []
|
||||
for (var i = 2015; i <= localDate.getUTCFullYear(); i++) {
|
||||
availableYears[i-2015] = i
|
||||
}
|
||||
return availableYears
|
||||
}
|
||||
+280
-126
@@ -9,20 +9,22 @@ import { withStyles } from '@material-ui/core/styles'
|
||||
import classNames from 'classnames'
|
||||
import styles from './styles'
|
||||
|
||||
import { types} from '../../../GraphQL/models'
|
||||
import { isDefined } from '../../../utils'
|
||||
import { types, startModes, availableMonths, processNames } from '../../../GraphQL/models'
|
||||
import { isDefined, getIndicatorYears } from '../../../utils'
|
||||
|
||||
import {
|
||||
MenuItem, Button, TextField, FormControl, InputLabel, Input, Typography,
|
||||
Paper, Dialog, DialogTitle, DialogContent, DialogContentText, DialogActions,
|
||||
Select, FormControlLabel, Checkbox
|
||||
Select, FormControlLabel, Checkbox, FormHelperText
|
||||
} from '@material-ui/core'
|
||||
|
||||
import { DateTimePicker } from 'material-ui-pickers';
|
||||
import NumberFormat from 'react-number-format'
|
||||
|
||||
import { DateTimePicker } from 'material-ui-pickers'
|
||||
import {
|
||||
ChevronLeft,
|
||||
ChevronRight,
|
||||
} from '@material-ui/icons';
|
||||
} from '@material-ui/icons'
|
||||
|
||||
class AddClone extends Component {
|
||||
|
||||
@@ -31,17 +33,23 @@ class AddClone extends Component {
|
||||
let user = localStorage.getItem('user')
|
||||
this.state = {
|
||||
user: JSON.parse(user),
|
||||
teamId:'',
|
||||
botId:'',
|
||||
mode:'',
|
||||
selectedBot: {'id':''},
|
||||
mode: '',
|
||||
resumeExecution: false,
|
||||
beginDatetime: DateTime.local().minus({ days: 8 }).startOf('day'),
|
||||
endDatetime: DateTime.local(),
|
||||
waitTime: 1,
|
||||
state : '',
|
||||
state: '',
|
||||
stateDatetime: 0,
|
||||
createDatetime: 0,
|
||||
runAsTeam: false,
|
||||
financialBeings:[],
|
||||
|
||||
// Indicator Bot
|
||||
startYear: 2019,
|
||||
endYear: 2019,
|
||||
month: 1,
|
||||
botProcessName: '',
|
||||
|
||||
//Error handlers
|
||||
nameError: false,
|
||||
@@ -49,8 +57,9 @@ class AddClone extends Component {
|
||||
botError: false,
|
||||
modeError: false,
|
||||
isNewCloneConfirmationOpen: false,
|
||||
serverResponse:'',
|
||||
serverError: false
|
||||
serverResponse: '',
|
||||
serverError: false,
|
||||
botProcessNameError: false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,8 +93,7 @@ class AddClone extends Component {
|
||||
|
||||
<Typography className={classes.typography} variant='subtitle1' align='justify'>
|
||||
A bot clone it's a copy of your bot running on a virtual machine.
|
||||
At the moment Live clones trade by default 0.001 BTC on Poloniex.
|
||||
Please select the team and bot you want to clone!
|
||||
Please select from your teams and bots the one you want to clone!
|
||||
</Typography>
|
||||
|
||||
<FormControl className={classNames(classes.form, classes.textField)} fullWidth>
|
||||
@@ -94,6 +102,8 @@ class AddClone extends Component {
|
||||
</InputLabel>
|
||||
<Query query={teams.GET_ALL_TEAMS_QUERY} >
|
||||
{({ loading, error, data }) => {
|
||||
if (error) return `Error! There has been an error loading teams.`
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<Select
|
||||
@@ -106,7 +116,9 @@ class AddClone extends Component {
|
||||
<MenuItem key='1' value='loading'>Loading...</MenuItem>
|
||||
</Select>
|
||||
)
|
||||
} else if(!isDefined(data.teams_FbByTeamMember)){
|
||||
}
|
||||
|
||||
if(!isDefined(data.teams_FbByTeamMember)){
|
||||
return (
|
||||
<Select
|
||||
value='noteams'
|
||||
@@ -118,121 +130,241 @@ class AddClone extends Component {
|
||||
<MenuItem key='1' value='noteams'>You don't have any teams yet.</MenuItem>
|
||||
</Select>
|
||||
)
|
||||
} else if (error) return `Error! There has been an error loading teams.`
|
||||
} else{
|
||||
this.financialBeings = data.teams_FbByTeamMember.fb
|
||||
}
|
||||
|
||||
return (
|
||||
<Select
|
||||
value={this.state.teamId}
|
||||
input={<Input />}
|
||||
className={classes.selectEmpty}
|
||||
onBlur={(e)=>this.setState({teamError:false})}
|
||||
error={this.state.teamError}
|
||||
onChange={e => this.setState({teamId:e.target.value})}
|
||||
>
|
||||
<MenuItem key={data.teams_FbByTeamMember.id}
|
||||
value={data.teams_FbByTeamMember.id}>
|
||||
{data.teams_FbByTeamMember.name + '/' + data.teams_FbByTeamMember.fb[0].name}
|
||||
</MenuItem>
|
||||
</Select>
|
||||
<Select
|
||||
value={this.state.selectedBot.id}
|
||||
displayEmpty
|
||||
className={classes.selectEmpty}
|
||||
onBlur={(e)=>this.setState({botError:false})}
|
||||
error={this.state.botError}
|
||||
onChange={e => this.setSelectedBot(e.target.value)}
|
||||
>
|
||||
{
|
||||
data.teams_FbByTeamMember.fb.map(financialBeing => (
|
||||
<MenuItem key={financialBeing.id} value={financialBeing.id}>
|
||||
{data.teams_FbByTeamMember.name + '/' + financialBeing.name}
|
||||
</MenuItem>
|
||||
))
|
||||
}
|
||||
</Select>
|
||||
)
|
||||
}}
|
||||
</Query>
|
||||
<FormHelperText>{this.state.selectedBot.kind}</FormHelperText>
|
||||
</FormControl>
|
||||
|
||||
<TextField
|
||||
select
|
||||
label="Running Mode"
|
||||
className={classNames(classes.margin, classes.textField, classes.form)}
|
||||
value={this.state.mode}
|
||||
onChange={(e)=> this.setState({mode:e.target.value})}
|
||||
onBlur={(e)=>this.setState({modeError:false})}
|
||||
error={this.state.modeError}
|
||||
fullWidth
|
||||
>
|
||||
{types.map(option => (
|
||||
<MenuItem key={option} value={option}>
|
||||
{option}
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
{ /* TRADER BOT */ }
|
||||
{ this.state.selectedBot.kind === "TRADER1" &&
|
||||
<React.Fragment>
|
||||
<Typography className={classes.typography} variant='subtitle1' align='justify'>
|
||||
At the moment Live Trading Clones trade by default 0.001 BTC on Poloniex.
|
||||
</Typography>
|
||||
|
||||
{ this.state.mode == "Backtest" &&
|
||||
<React.Fragment>
|
||||
<DateTimePicker
|
||||
autoOk
|
||||
disableFuture
|
||||
format="DD' at 'HH:mm"
|
||||
ampm={false}
|
||||
showTabs={false}
|
||||
leftArrowIcon={<ChevronLeft />}
|
||||
rightArrowIcon={<ChevronRight />}
|
||||
value={this.state.beginDatetime}
|
||||
label='Backtest Start Date'
|
||||
onChange={newVal => this.setState({ beginDatetime: newVal })}
|
||||
className={classNames(classes.form, classes.textField)}
|
||||
fullWidth
|
||||
/>
|
||||
<TextField
|
||||
select
|
||||
label="Running Mode"
|
||||
className={classNames(classes.margin, classes.textField, classes.form)}
|
||||
value={this.state.mode}
|
||||
onChange={(e)=> this.setState({mode:e.target.value})}
|
||||
onBlur={(e)=>this.setState({modeError:false})}
|
||||
error={this.state.modeError}
|
||||
fullWidth
|
||||
>
|
||||
{types.map(option => (
|
||||
<MenuItem key={option} value={option}>
|
||||
{option}
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
|
||||
<DateTimePicker
|
||||
autoOk
|
||||
disableFuture
|
||||
format="DD' at 'HH:mm"
|
||||
ampm={false}
|
||||
showTabs={false}
|
||||
leftArrowIcon={<ChevronLeft />}
|
||||
rightArrowIcon={<ChevronRight />}
|
||||
value={this.state.endDatetime}
|
||||
label='Backtest End Date'
|
||||
onChange={newVal => this.setState({ endDatetime: newVal })}
|
||||
className={classNames(classes.form, classes.textField)}
|
||||
fullWidth
|
||||
/>
|
||||
{ this.state.mode == "Backtest" &&
|
||||
<React.Fragment>
|
||||
<DateTimePicker
|
||||
autoOk
|
||||
disableFuture
|
||||
format="DD' at 'HH:mm"
|
||||
ampm={false}
|
||||
showTabs={false}
|
||||
leftArrowIcon={<ChevronLeft />}
|
||||
rightArrowIcon={<ChevronRight />}
|
||||
value={this.state.beginDatetime}
|
||||
label='Backtest Start Date'
|
||||
onChange={newVal => this.setState({ beginDatetime: newVal })}
|
||||
className={classNames(classes.form, classes.textField)}
|
||||
fullWidth
|
||||
/>
|
||||
|
||||
<TextField
|
||||
id="waitTime"
|
||||
label="Wait Time"
|
||||
className={classNames(classes.form, classes.textField)}
|
||||
value={this.state.waitTime}
|
||||
onChange={(e)=>this.setState({waitTime:e.target.value})}
|
||||
fullWidth
|
||||
/>
|
||||
</React.Fragment>
|
||||
}
|
||||
<DateTimePicker
|
||||
autoOk
|
||||
disableFuture
|
||||
format="DD' at 'HH:mm"
|
||||
ampm={false}
|
||||
showTabs={false}
|
||||
leftArrowIcon={<ChevronLeft />}
|
||||
rightArrowIcon={<ChevronRight />}
|
||||
value={this.state.endDatetime}
|
||||
label='Backtest End Date'
|
||||
onChange={newVal => this.setState({ endDatetime: newVal })}
|
||||
className={classNames(classes.form, classes.textField)}
|
||||
fullWidth
|
||||
/>
|
||||
|
||||
<Typography className={classes.typography} variant='subtitle1' align='justify'>
|
||||
If Run as Team is selected, the clone will be taken from the
|
||||
team respository instead of your own team member folder.
|
||||
Competitions runs from the team respository.
|
||||
</Typography>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={this.state.runAsTeam}
|
||||
onChange={(e)=>this.setState({runAsTeam:e.target.checked })}
|
||||
value="runAsTeam"
|
||||
color="primary"
|
||||
/>
|
||||
}
|
||||
label="Run as Team"
|
||||
className={classNames(classes.form, classes.textField)}
|
||||
/>
|
||||
<TextField
|
||||
id="waitTime"
|
||||
label="Wait Time"
|
||||
className={classNames(classes.form, classes.textField)}
|
||||
value={this.state.waitTime}
|
||||
onChange={(e)=>this.setState({waitTime:e.target.value})}
|
||||
fullWidth
|
||||
/>
|
||||
</React.Fragment>
|
||||
}
|
||||
|
||||
<Typography className={classes.typography} variant='subtitle1' align='justify'>
|
||||
The Resume Execution option let's you pick up the context of
|
||||
the last execution and continue from there.
|
||||
</Typography>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={this.state.resumeExecution}
|
||||
onChange={(e)=>this.setState({resumeExecution:e.target.checked })}
|
||||
value="resumeExecution"
|
||||
color="primary"
|
||||
/>
|
||||
}
|
||||
label="Resume Execution"
|
||||
className={classNames(classes.form, classes.textField)}
|
||||
/>
|
||||
<Typography className={classes.typography} variant='subtitle1' align='justify'>
|
||||
If Run as Team is selected, the clone will be taken from the
|
||||
team respository instead of your own team member folder.
|
||||
Competitions runs from the team respository.
|
||||
</Typography>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={this.state.runAsTeam}
|
||||
onChange={(e)=>this.setState({runAsTeam:e.target.checked })}
|
||||
value="runAsTeam"
|
||||
color="primary"
|
||||
/>
|
||||
}
|
||||
label="Run as Team"
|
||||
className={classNames(classes.form, classes.textField)}
|
||||
/>
|
||||
|
||||
<Typography className={classes.typography} variant='subtitle1' align='justify'>
|
||||
The Resume Execution option let's you pick up the context of
|
||||
the last execution and continue from there.
|
||||
</Typography>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={this.state.resumeExecution}
|
||||
onChange={(e)=>this.setState({resumeExecution:e.target.checked })}
|
||||
value="resumeExecution"
|
||||
color="primary"
|
||||
/>
|
||||
}
|
||||
label="Resume Execution"
|
||||
className={classNames(classes.form, classes.textField)}
|
||||
/>
|
||||
</React.Fragment>
|
||||
}
|
||||
|
||||
{ /* INDICATOR AND EXTRACTOR BOTS */ }
|
||||
{ (this.state.selectedBot.kind === "TRADER"
|
||||
|| this.state.selectedBot.kind === "EXTRACTOR") &&
|
||||
<React.Fragment>
|
||||
<TextField
|
||||
label="Process Name"
|
||||
className={classNames(classes.textField, classes.form)}
|
||||
value={this.state.botProcessName}
|
||||
onChange={(e)=> this.setState({botProcessName:e.target.value})}
|
||||
onBlur={(e)=>this.setState({botProcessNameError:false})}
|
||||
error={this.state.botProcessNameError}
|
||||
fullWidth
|
||||
/>
|
||||
|
||||
<TextField
|
||||
select
|
||||
label="Running Mode"
|
||||
className={classNames(classes.margin, classes.textField, classes.form)}
|
||||
value={this.state.mode}
|
||||
onChange={(e)=> this.setState({mode:e.target.value})}
|
||||
onBlur={(e)=>this.setState({modeError:false})}
|
||||
error={this.state.modeError}
|
||||
fullWidth
|
||||
>
|
||||
{startModes.map(option => (
|
||||
<MenuItem key={option} value={option}>
|
||||
{option}
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
|
||||
{ this.state.mode === "All Months" &&
|
||||
<React.Fragment>
|
||||
<TextField
|
||||
id="beginYearInput"
|
||||
select
|
||||
label="Start Year"
|
||||
className={classNames(classes.textField, classes.form)}
|
||||
value={this.state.startYear}
|
||||
onChange={(e)=> this.setState({startYear:e.target.value})}
|
||||
fullWidth
|
||||
>
|
||||
{getIndicatorYears().map((option, index) => (
|
||||
<MenuItem key={option} value={index}>
|
||||
{option}
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
|
||||
<TextField
|
||||
id="endYearInput"
|
||||
select
|
||||
label="End Year"
|
||||
className={classNames(classes.textField, classes.form)}
|
||||
value={this.state.endYear}
|
||||
onChange={(e)=> this.setState({endYear:e.target.value})}
|
||||
fullWidth
|
||||
>
|
||||
{getIndicatorYears().map((option, index) => (
|
||||
<MenuItem key={option} value={index}>
|
||||
{option}
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
</React.Fragment>
|
||||
}
|
||||
|
||||
{ this.state.mode === "One Month" &&
|
||||
<React.Fragment>
|
||||
<TextField
|
||||
id="beginYearInput"
|
||||
select
|
||||
label="Year"
|
||||
className={classNames(classes.textField, classes.form)}
|
||||
value={this.state.startYear}
|
||||
onChange={(e)=> this.setState({startYear:e.target.value})}
|
||||
fullWidth
|
||||
>
|
||||
{getIndicatorYears().map((option, index) => (
|
||||
<MenuItem key={option} value={index}>
|
||||
{option}
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
|
||||
<TextField
|
||||
id="endYearInput"
|
||||
select
|
||||
label="Month"
|
||||
className={classNames(classes.textField, classes.form)}
|
||||
value={this.state.month}
|
||||
onChange={(e)=> this.setState({month:e.target.value})}
|
||||
fullWidth
|
||||
>
|
||||
{availableMonths.map(option => (
|
||||
<MenuItem key={option} value={option}>
|
||||
{option}
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
</React.Fragment>
|
||||
}
|
||||
</React.Fragment>
|
||||
}
|
||||
|
||||
<div className={classes.actionButton} >
|
||||
<Button
|
||||
@@ -268,6 +400,17 @@ class AddClone extends Component {
|
||||
);
|
||||
}
|
||||
|
||||
setSelectedBot(botId){
|
||||
if(isDefined(this.financialBeings)){
|
||||
for (var i = 0; i < this.financialBeings.length; i++) {
|
||||
if(this.financialBeings[i].id === botId){
|
||||
this.setState({selectedBot:this.financialBeings[i]})
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async submitForm(e){
|
||||
e.preventDefault()
|
||||
let error = this.validate()
|
||||
@@ -289,23 +432,28 @@ class AddClone extends Component {
|
||||
async createCloneOnServer(){
|
||||
let variables = {
|
||||
clone:{
|
||||
teamId: this.state.teamId,
|
||||
botId: this.state.botId,
|
||||
botId: this.state.selectedBot.id,
|
||||
mode: this.state.mode,
|
||||
resumeExecution: this.state.resumeExecution,
|
||||
runAsTeam: this.state.runAsTeam
|
||||
}
|
||||
}
|
||||
|
||||
if(this.state.mode == "Backtest"){
|
||||
if(this.state.mode === "Backtest"){
|
||||
variables.clone.beginDatetime = this.state.beginDatetime.valueOf() / 1000|0
|
||||
variables.clone.endDatetime = this.state.endDatetime.valueOf() / 1000|0
|
||||
variables.clone.waitTime = this.state.waitTime
|
||||
}
|
||||
|
||||
if(this.state.selectedBot.kind !== "TRADER"){
|
||||
variables.clone.botProcessName = this.state.botProcessName
|
||||
variables.clone.startYear = this.state.startYear
|
||||
variables.clone.endYear = this.state.endYear
|
||||
variables.clone.month = this.state.month
|
||||
}
|
||||
|
||||
return this.props.addCloneMutation({
|
||||
variables: variables
|
||||
//refetchQueries: [{query: getClonesQuery}],
|
||||
})
|
||||
}
|
||||
|
||||
@@ -320,9 +468,8 @@ class AddClone extends Component {
|
||||
|
||||
if(!this.state.serverError)
|
||||
this.setState({
|
||||
teamId:'',
|
||||
botId:'',
|
||||
mode:'',
|
||||
selectedBot: {'id':''},
|
||||
mode: '',
|
||||
resumeExecution: false,
|
||||
beginDatetime: DateTime.local().minus({ days: 8 }).startOf('day'),
|
||||
endDatetime: DateTime.local(),
|
||||
@@ -331,6 +478,7 @@ class AddClone extends Component {
|
||||
stateDatetime: 0,
|
||||
createDatetime: 0,
|
||||
runAsTeam: false,
|
||||
botProcessName: '',
|
||||
|
||||
//Error handlers
|
||||
nameError: false,
|
||||
@@ -339,14 +487,15 @@ class AddClone extends Component {
|
||||
modeError: false,
|
||||
isNewCloneConfirmationOpen: false,
|
||||
serverResponse: '',
|
||||
serverError: false
|
||||
serverError: false,
|
||||
botProcessNameError: false
|
||||
})
|
||||
};
|
||||
|
||||
validate(){
|
||||
let isError = false
|
||||
|
||||
if(this.state.teamId.length < 1) {
|
||||
if(this.state.selectedBot.length < 1) {
|
||||
isError = true
|
||||
this.setState(state => ({ teamError: true }));
|
||||
}
|
||||
@@ -356,6 +505,11 @@ class AddClone extends Component {
|
||||
this.setState(state => ({ modeError: true }));
|
||||
}
|
||||
|
||||
if(this.state.botProcessName.length < 1) {
|
||||
isError = true
|
||||
this.setState(state => ({ botProcessNameError: true }));
|
||||
}
|
||||
|
||||
return isError;
|
||||
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ class HistoryClones extends Component {
|
||||
<TopBar
|
||||
size='big'
|
||||
title='Bot Clone History'
|
||||
text="You don't have any Bot Clone yet. Once you create one you will find it here."
|
||||
text="You don't have any Clone yet. Once you create one you will find it here."
|
||||
backgroundUrl='https://superalgos.org/img/photos/ecosystem.jpg'
|
||||
/>
|
||||
)
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
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 = 'All Months'
|
||||
export const ONE_MONTH = 'One Month'
|
||||
export const NO_TIME = 'No Time'
|
||||
|
||||
export const CloneModeEnum = [
|
||||
LIVE,
|
||||
BACKTEST,
|
||||
COMPETITION
|
||||
];
|
||||
COMPETITION,
|
||||
ALL_MONTHS,
|
||||
ONE_MONTH,
|
||||
NO_TIME
|
||||
]
|
||||
|
||||
export default CloneModeEnum;
|
||||
export default CloneModeEnum
|
||||
File renamed without changes.
@@ -1,98 +0,0 @@
|
||||
import logger from '../config/logger'
|
||||
import { toPlatformDatetime } from '../config/utils'
|
||||
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';
|
||||
|
||||
const platformExecutionContext = async (clone, cloneName) => {
|
||||
try {
|
||||
logger.info("createClone %j", cloneName)
|
||||
const client = new Client({config: config.fromKubeconfig(), version: '1.9'})
|
||||
|
||||
// Make changes to base deployment config
|
||||
deploymentManifest.metadata.name = cloneName
|
||||
|
||||
logger.debug("createClone Set basic environment configuration.")
|
||||
let env = envConfig
|
||||
|
||||
logger.debug("createClone Configuration for team, bot and process.")
|
||||
env.push({
|
||||
"name": "DEV_TEAM",
|
||||
"value": clone.teamId
|
||||
})
|
||||
|
||||
env.push({
|
||||
"name": "BOT",
|
||||
"value": clone.botId
|
||||
})
|
||||
|
||||
// TODO allow other types
|
||||
env.push({
|
||||
"name": "PROCESS",
|
||||
"value": "Trading-Process"
|
||||
})
|
||||
|
||||
// TODO allow other types
|
||||
env.push({
|
||||
"name": "TYPE",
|
||||
"value": "Trading"
|
||||
})
|
||||
|
||||
env.push({
|
||||
"name": "RUN_AS_TEAM",
|
||||
"value": clone.runAsTeam.toString()
|
||||
})
|
||||
|
||||
env.push({
|
||||
"name": "USER_LOGGED_IN",
|
||||
"value": clone.userLoggedIn
|
||||
})
|
||||
|
||||
logger.debug("createClone Configuration for the execution.")
|
||||
env.push({
|
||||
"name": "START_MODE",
|
||||
"value": clone.mode.toLowerCase()
|
||||
})
|
||||
|
||||
env.push({
|
||||
"name": "RESUME_EXECUTION",
|
||||
"value": clone.resumeExecution.toString()
|
||||
})
|
||||
|
||||
if(clone.mode === BACKTEST){
|
||||
env.push({
|
||||
"name": "BEGIN_DATE_TIME",
|
||||
"value": toPlatformDatetime(clone.beginDatetime)
|
||||
})
|
||||
|
||||
env.push({
|
||||
"name": "END_DATE_TIME",
|
||||
"value": toPlatformDatetime(clone.endDatetime)
|
||||
})
|
||||
|
||||
env.push({
|
||||
"name": "WAIT_TIME",
|
||||
"value": clone.waitTime.toString()
|
||||
})
|
||||
}
|
||||
|
||||
deploymentManifest.spec.template.spec.containers[0].env = env
|
||||
|
||||
// Create a new Deployment
|
||||
const create = await client.apis.batch.v1.namespaces('default').jobs.post(
|
||||
{ body: deploymentManifest })
|
||||
logger.debug("Create: %j ", create)
|
||||
|
||||
// Fetch the Deployment we just created
|
||||
const deployment = await client.apis.batch.v1.namespaces('default').jobs(
|
||||
deploymentManifest.metadata.name).get()
|
||||
logger.debug("Job: %j ", deployment)
|
||||
|
||||
logger.info("createClone %j succesfull", cloneName)
|
||||
} catch (err) {
|
||||
throw new KubernateError(err)
|
||||
}
|
||||
}
|
||||
export default platformExecutionContext
|
||||
@@ -1,98 +0,0 @@
|
||||
import logger from '../config/logger'
|
||||
import { toPlatformDatetime } from '../config/utils'
|
||||
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';
|
||||
|
||||
const platformExecutionContext = async (clone, cloneName) => {
|
||||
try {
|
||||
logger.info("createClone %j", cloneName)
|
||||
const client = new Client({config: config.fromKubeconfig(), version: '1.9'})
|
||||
|
||||
// Make changes to base deployment config
|
||||
deploymentManifest.metadata.name = cloneName
|
||||
|
||||
logger.debug("createClone Set basic environment configuration.")
|
||||
let env = envConfig
|
||||
|
||||
logger.debug("createClone Configuration for team, bot and process.")
|
||||
env.push({
|
||||
"name": "DEV_TEAM",
|
||||
"value": clone.teamId
|
||||
})
|
||||
|
||||
env.push({
|
||||
"name": "BOT",
|
||||
"value": clone.botId
|
||||
})
|
||||
|
||||
// TODO allow other types
|
||||
env.push({
|
||||
"name": "PROCESS",
|
||||
"value": "Trading-Process"
|
||||
})
|
||||
|
||||
// TODO allow other types
|
||||
env.push({
|
||||
"name": "TYPE",
|
||||
"value": "Trading"
|
||||
})
|
||||
|
||||
env.push({
|
||||
"name": "RUN_AS_TEAM",
|
||||
"value": clone.runAsTeam.toString()
|
||||
})
|
||||
|
||||
env.push({
|
||||
"name": "USER_LOGGED_IN",
|
||||
"value": clone.userLoggedIn
|
||||
})
|
||||
|
||||
logger.debug("createClone Configuration for the execution.")
|
||||
env.push({
|
||||
"name": "START_MODE",
|
||||
"value": clone.mode.toLowerCase()
|
||||
})
|
||||
|
||||
env.push({
|
||||
"name": "RESUME_EXECUTION",
|
||||
"value": clone.resumeExecution.toString()
|
||||
})
|
||||
|
||||
if(clone.mode === BACKTEST){
|
||||
env.push({
|
||||
"name": "BEGIN_DATE_TIME",
|
||||
"value": toPlatformDatetime(clone.beginDatetime)
|
||||
})
|
||||
|
||||
env.push({
|
||||
"name": "END_DATE_TIME",
|
||||
"value": toPlatformDatetime(clone.endDatetime)
|
||||
})
|
||||
|
||||
env.push({
|
||||
"name": "WAIT_TIME",
|
||||
"value": clone.waitTime.toString()
|
||||
})
|
||||
}
|
||||
|
||||
deploymentManifest.spec.template.spec.containers[0].env = env
|
||||
|
||||
// Create a new Deployment
|
||||
const create = await client.apis.batch.v1.namespaces('default').jobs.post(
|
||||
{ body: deploymentManifest })
|
||||
logger.debug("Create: %j ", create)
|
||||
|
||||
// Fetch the Deployment we just created
|
||||
const deployment = await client.apis.batch.v1.namespaces('default').jobs(
|
||||
deploymentManifest.metadata.name).get()
|
||||
logger.debug("Job: %j ", deployment)
|
||||
|
||||
logger.info("createClone %j succesfull", cloneName)
|
||||
} catch (err) {
|
||||
throw new KubernateError(err)
|
||||
}
|
||||
}
|
||||
export default platformExecutionContext
|
||||
@@ -46,7 +46,7 @@ const resolve = async(parent, { clone }, context) => {
|
||||
|
||||
logger.debug('addClone -> Checking existing clone %j', existingClone)
|
||||
if(isDefined(existingClone) && existingClone.length > 0){
|
||||
throw new CustomError('You can only create one clone per mode. Remove the'
|
||||
throw new CustomError('You can only have one active clone by mode. Remove the'
|
||||
+ ' existing clone of type: ' + clone.mode + ' and try again.')
|
||||
}
|
||||
|
||||
@@ -76,8 +76,7 @@ const resolve = async(parent, { clone }, context) => {
|
||||
`,
|
||||
},
|
||||
headers: {
|
||||
authorization: context.authorization,
|
||||
preshared: process.env.OPERATIONS_API_PRESHARED
|
||||
authorization: context.authorization
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
Reference in new issue
Block a user