From a8ac7385d6e198cab21f404aaefc1b45fbbb1e0f Mon Sep 17 00:00:00 2001 From: "mati108@gmail.com" <34651529+matbenitez@users.noreply.github.com> Date: Mon, 28 Jan 2019 10:56:00 -0300 Subject: [PATCH] Adding support for Indicators and Extractors --- client/package-lock.json | 12 +- client/package.json | 5 +- client/src/GraphQL/Calls/teams.js | 21 +- client/src/GraphQL/models.js | 7 +- client/src/utils/index.js | 9 + client/src/views/Clone/Add/index.js | 406 ++++++++++++------ client/src/views/Clone/History/index.js | 2 +- server/src/enums/CloneMode.js | 18 +- .../teams_FbByTeamMember.js} | 0 server/src/platform/fileStorageReader.js | 98 ----- .../src/platform/platformExecutionContext.js | 98 ----- .../src/schema/mutations/AddCloneMutation.js | 5 +- 12 files changed, 325 insertions(+), 356 deletions(-) rename server/src/{platform/downloadBlob.js => graphQLCalls/teams_FbByTeamMember.js} (100%) delete mode 100644 server/src/platform/fileStorageReader.js delete mode 100644 server/src/platform/platformExecutionContext.js diff --git a/client/package-lock.json b/client/package-lock.json index 9a3c14063..2f4b4a7ba 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -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", diff --git a/client/package.json b/client/package.json index 4fcd2d33b..81d6b3829 100644 --- a/client/package.json +++ b/client/package.json @@ -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": { diff --git a/client/src/GraphQL/Calls/teams.js b/client/src/GraphQL/Calls/teams.js index 1a5f02f5b..7329d3e07 100644 --- a/client/src/GraphQL/Calls/teams.js +++ b/client/src/GraphQL/Calls/teams.js @@ -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 }; diff --git a/client/src/GraphQL/models.js b/client/src/GraphQL/models.js index 252f1ee61..474df1fcf 100644 --- a/client/src/GraphQL/models.js +++ b/client/src/GraphQL/models.js @@ -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 } diff --git a/client/src/utils/index.js b/client/src/utils/index.js index d81838754..e5e223f3c 100644 --- a/client/src/utils/index.js +++ b/client/src/utils/index.js @@ -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 +} diff --git a/client/src/views/Clone/Add/index.js b/client/src/views/Clone/Add/index.js index c86adc833..6b3c76462 100644 --- a/client/src/views/Clone/Add/index.js +++ b/client/src/views/Clone/Add/index.js @@ -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 { 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! @@ -94,6 +102,8 @@ class AddClone extends Component { {({ loading, error, data }) => { + if (error) return `Error! There has been an error loading teams.` + if (loading) { return ( ) - } else if(!isDefined(data.teams_FbByTeamMember)){ + } + + if(!isDefined(data.teams_FbByTeamMember)){ return ( ) - } else if (error) return `Error! There has been an error loading teams.` + } else{ + this.financialBeings = data.teams_FbByTeamMember.fb + } return ( - + ) }} + {this.state.selectedBot.kind} - this.setState({mode:e.target.value})} - onBlur={(e)=>this.setState({modeError:false})} - error={this.state.modeError} - fullWidth - > - {types.map(option => ( - - {option} - - ))} - + { /* TRADER BOT */ } + { this.state.selectedBot.kind === "TRADER1" && + + + At the moment Live Trading Clones trade by default 0.001 BTC on Poloniex. + - { this.state.mode == "Backtest" && - - } - rightArrowIcon={} - value={this.state.beginDatetime} - label='Backtest Start Date' - onChange={newVal => this.setState({ beginDatetime: newVal })} - className={classNames(classes.form, classes.textField)} - fullWidth - /> + this.setState({mode:e.target.value})} + onBlur={(e)=>this.setState({modeError:false})} + error={this.state.modeError} + fullWidth + > + {types.map(option => ( + + {option} + + ))} + - } - rightArrowIcon={} - 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" && + + } + rightArrowIcon={} + value={this.state.beginDatetime} + label='Backtest Start Date' + onChange={newVal => this.setState({ beginDatetime: newVal })} + className={classNames(classes.form, classes.textField)} + fullWidth + /> - this.setState({waitTime:e.target.value})} - fullWidth - /> - - } + } + rightArrowIcon={} + value={this.state.endDatetime} + label='Backtest End Date' + onChange={newVal => this.setState({ endDatetime: newVal })} + className={classNames(classes.form, classes.textField)} + fullWidth + /> - - 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. - - this.setState({runAsTeam:e.target.checked })} - value="runAsTeam" - color="primary" - /> - } - label="Run as Team" - className={classNames(classes.form, classes.textField)} - /> + this.setState({waitTime:e.target.value})} + fullWidth + /> + + } - - The Resume Execution option let's you pick up the context of - the last execution and continue from there. - - this.setState({resumeExecution:e.target.checked })} - value="resumeExecution" - color="primary" - /> - } - label="Resume Execution" - className={classNames(classes.form, classes.textField)} - /> + + 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. + + this.setState({runAsTeam:e.target.checked })} + value="runAsTeam" + color="primary" + /> + } + label="Run as Team" + className={classNames(classes.form, classes.textField)} + /> + + + The Resume Execution option let's you pick up the context of + the last execution and continue from there. + + this.setState({resumeExecution:e.target.checked })} + value="resumeExecution" + color="primary" + /> + } + label="Resume Execution" + className={classNames(classes.form, classes.textField)} + /> + + } + + { /* INDICATOR AND EXTRACTOR BOTS */ } + { (this.state.selectedBot.kind === "TRADER" + || this.state.selectedBot.kind === "EXTRACTOR") && + + this.setState({botProcessName:e.target.value})} + onBlur={(e)=>this.setState({botProcessNameError:false})} + error={this.state.botProcessNameError} + fullWidth + /> + + this.setState({mode:e.target.value})} + onBlur={(e)=>this.setState({modeError:false})} + error={this.state.modeError} + fullWidth + > + {startModes.map(option => ( + + {option} + + ))} + + + { this.state.mode === "All Months" && + + this.setState({startYear:e.target.value})} + fullWidth + > + {getIndicatorYears().map((option, index) => ( + + {option} + + ))} + + + this.setState({endYear:e.target.value})} + fullWidth + > + {getIndicatorYears().map((option, index) => ( + + {option} + + ))} + + + } + + { this.state.mode === "One Month" && + + this.setState({startYear:e.target.value})} + fullWidth + > + {getIndicatorYears().map((option, index) => ( + + {option} + + ))} + + + this.setState({month:e.target.value})} + fullWidth + > + {availableMonths.map(option => ( + + {option} + + ))} + + + } + + }