mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-25 16:25:16 +00:00
query symbols and use react number format
This commit is contained in:
parent
578451bb51
commit
f94a45de40
|
@ -27,12 +27,19 @@ export function testSessionConnection(session, cb) {
|
|||
}
|
||||
|
||||
export function querySessions(cb) {
|
||||
axios.get(baseURL + '/api/sessions', {})
|
||||
return axios.get(baseURL + '/api/sessions', {})
|
||||
.then(response => {
|
||||
cb(response.data.sessions)
|
||||
});
|
||||
}
|
||||
|
||||
export function querySessionSymbols(sessionName, cb) {
|
||||
return axios.get(baseURL + `/api/sessions/${ sessionName }/symbols`, {})
|
||||
.then(response => {
|
||||
cb(response.data.symbols)
|
||||
});
|
||||
}
|
||||
|
||||
export function queryTrades(params, cb) {
|
||||
axios.get(baseURL + '/api/trades', {params: params})
|
||||
.then(response => {
|
||||
|
|
|
@ -113,7 +113,7 @@ export default function AddExchangeSessionForm({onBack, onAdded}) {
|
|||
|
||||
<Grid item xs={12}>
|
||||
<FormControl className={classes.formControl}>
|
||||
<InputLabel id="exchange-type-select-label">Exchange Type</InputLabel>
|
||||
<InputLabel id="exchange-type-select-label">Exchange</InputLabel>
|
||||
<Select
|
||||
labelId="exchange-type-select-label"
|
||||
id="exchange-type-select"
|
||||
|
|
|
@ -52,10 +52,10 @@ export default function ConfigureDatabaseForm({ onConfigured }) {
|
|||
setTimeout(onConfigured, 3000);
|
||||
}
|
||||
|
||||
}).catch((reason) => {
|
||||
console.error(reason);
|
||||
}).catch((err) => {
|
||||
console.error(err);
|
||||
setTesting(false);
|
||||
setTestResponse(reason);
|
||||
setTestResponse(err.response.data);
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -65,10 +65,10 @@ export default function ConfigureDatabaseForm({ onConfigured }) {
|
|||
console.log(response)
|
||||
setTesting(false)
|
||||
setTestResponse(response)
|
||||
}).catch((reason) => {
|
||||
console.error(reason)
|
||||
}).catch((err) => {
|
||||
console.error(err)
|
||||
setTesting(false)
|
||||
setTestResponse(reason)
|
||||
setTestResponse(err.response.data)
|
||||
})
|
||||
};
|
||||
|
||||
|
|
286
frontend/components/ConfigureGridStrategyForm.js
Normal file
286
frontend/components/ConfigureGridStrategyForm.js
Normal file
|
@ -0,0 +1,286 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import Grid from '@material-ui/core/Grid';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
|
||||
import {makeStyles} from '@material-ui/core/styles';
|
||||
import {querySessions, querySessionSymbols} from "../api/bbgo";
|
||||
|
||||
import TextField from '@material-ui/core/TextField';
|
||||
import FormControlLabel from '@material-ui/core/FormControlLabel';
|
||||
import FormHelperText from '@material-ui/core/FormHelperText';
|
||||
import InputLabel from '@material-ui/core/InputLabel';
|
||||
import FormControl from '@material-ui/core/FormControl';
|
||||
|
||||
import Checkbox from '@material-ui/core/Checkbox';
|
||||
import Select from '@material-ui/core/Select';
|
||||
import MenuItem from '@material-ui/core/MenuItem';
|
||||
|
||||
import Alert from '@material-ui/lab/Alert';
|
||||
import Box from "@material-ui/core/Box";
|
||||
|
||||
import NumberFormat from 'react-number-format';
|
||||
|
||||
function NumberFormatCustom(props) {
|
||||
const { inputRef, onChange, ...other } = props;
|
||||
|
||||
return (
|
||||
<NumberFormat
|
||||
{...other}
|
||||
getInputRef={inputRef}
|
||||
onValueChange={(values) => {
|
||||
onChange({
|
||||
target: {
|
||||
name: props.name,
|
||||
value: values.value,
|
||||
},
|
||||
});
|
||||
}}
|
||||
thousandSeparator
|
||||
isNumericString
|
||||
prefix="$"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
NumberFormatCustom.propTypes = {
|
||||
inputRef: PropTypes.func.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
formControl: {
|
||||
marginTop: theme.spacing(1),
|
||||
marginBottom: theme.spacing(1),
|
||||
minWidth: 120,
|
||||
},
|
||||
buttons: {
|
||||
display: 'flex',
|
||||
justifyContent: 'flex-end',
|
||||
marginTop: theme.spacing(2),
|
||||
paddingTop: theme.spacing(2),
|
||||
paddingBottom: theme.spacing(2),
|
||||
'& > *': {
|
||||
marginLeft: theme.spacing(1),
|
||||
}
|
||||
},
|
||||
}));
|
||||
|
||||
|
||||
export default function ConfigureGridStrategyForm({onBack, onConfigured}) {
|
||||
const classes = useStyles();
|
||||
|
||||
const [sessions, setSessions] = React.useState([]);
|
||||
|
||||
const [activeSessionSymbols, setActiveSessionSymbols] = React.useState([]);
|
||||
|
||||
const [selectedSessionName, setSelectedSessionName] = React.useState(null);
|
||||
|
||||
const [selectedSymbol, setSelectedSymbol] = React.useState('');
|
||||
|
||||
const [upperPrice, setUpperPrice] = React.useState(30000.0);
|
||||
const [lowerPrice, setLowerPrice] = React.useState(10000.0);
|
||||
|
||||
const [response, setResponse] = React.useState({});
|
||||
|
||||
React.useEffect(() => {
|
||||
querySessions((sessions) => {
|
||||
setSessions(sessions)
|
||||
});
|
||||
}, [])
|
||||
|
||||
const handleAdd = (event) => {
|
||||
|
||||
};
|
||||
|
||||
const handleSessionChange = (event) => {
|
||||
const sessionName = event.target.value;
|
||||
setSelectedSessionName(sessionName)
|
||||
|
||||
querySessionSymbols(sessionName, (symbols) => {
|
||||
setActiveSessionSymbols(symbols);
|
||||
})
|
||||
};
|
||||
|
||||
const sessionMenuItems = sessions.map((session, index) => {
|
||||
return (
|
||||
<MenuItem key={session.name} value={session.name}>
|
||||
{session.name}
|
||||
</MenuItem>
|
||||
);
|
||||
})
|
||||
|
||||
const symbolMenuItems = activeSessionSymbols.map((symbol, index) => {
|
||||
return (
|
||||
<MenuItem key={symbol} value={symbol}>
|
||||
{symbol}
|
||||
</MenuItem>
|
||||
);
|
||||
})
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Typography variant="h6" gutterBottom>
|
||||
Add Grid Strategy
|
||||
</Typography>
|
||||
|
||||
<Typography variant="body1" gutterBottom>
|
||||
Fixed price band grid strategy uses the fixed price band to place buy/sell orders.
|
||||
This strategy places sell orders above the current price, places buy orders below the current price.
|
||||
If any of the order is executed, then it will automatically place a new profit order on the reverse
|
||||
side.
|
||||
</Typography>
|
||||
|
||||
<Grid container spacing={3}>
|
||||
<Grid item xs={12}>
|
||||
<FormControl className={classes.formControl}>
|
||||
<InputLabel id="session-select-label">Session</InputLabel>
|
||||
<Select
|
||||
labelId="session-select-label"
|
||||
id="session-select"
|
||||
value={selectedSessionName ? selectedSessionName : ''}
|
||||
onChange={handleSessionChange}
|
||||
>
|
||||
{sessionMenuItems}
|
||||
</Select>
|
||||
</FormControl>
|
||||
<FormHelperText id="session-select-helper-text">
|
||||
Select the exchange session you want to mount this strategy.
|
||||
</FormHelperText>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12}>
|
||||
<FormControl className={classes.formControl}>
|
||||
<InputLabel id="symbol-select-label">Market</InputLabel>
|
||||
<Select
|
||||
labelId="symbol-select-label"
|
||||
id="symbol-select"
|
||||
value={selectedSymbol ? selectedSymbol : ''}
|
||||
onChange={(event) => {
|
||||
setSelectedSymbol(event.target.value);
|
||||
}}>
|
||||
{symbolMenuItems}
|
||||
</Select>
|
||||
</FormControl>
|
||||
<FormHelperText id="session-select-helper-text">
|
||||
Select the market you want to run this strategy
|
||||
</FormHelperText>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12}>
|
||||
<TextField
|
||||
id="upperPrice"
|
||||
name="upper_price"
|
||||
label="Upper Price"
|
||||
fullWidth
|
||||
required
|
||||
onChange={(event) => {
|
||||
if (event.target.value) {
|
||||
const v = parseFloat(event.target.value)
|
||||
if (!isNaN(v)) {
|
||||
setUpperPrice(v);
|
||||
}
|
||||
}
|
||||
}}
|
||||
value={upperPrice}
|
||||
InputProps={{
|
||||
inputComponent: NumberFormatCustom,
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12}>
|
||||
<TextField
|
||||
id="lowerPrice"
|
||||
name="lower_price"
|
||||
label="Lower Price"
|
||||
fullWidth
|
||||
required
|
||||
onChange={(event) => {
|
||||
if (event.target.value) {
|
||||
const v = parseFloat(event.target.value)
|
||||
if (!isNaN(v)) {
|
||||
setLowerPrice(v);
|
||||
}
|
||||
}
|
||||
}}
|
||||
value={lowerPrice}
|
||||
InputProps={{
|
||||
inputComponent: NumberFormatCustom,
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12} sm={6}>
|
||||
<FormControlLabel
|
||||
control={<Checkbox color="secondary" name="custom_session_name"
|
||||
onChange={(event) => {
|
||||
|
||||
}} value="1"/>}
|
||||
label="Custom exchange session name"
|
||||
/>
|
||||
<FormHelperText id="session-name-helper-text">
|
||||
By default, the session name will be the exchange type name,
|
||||
e.g. <code>binance</code> or <code>max</code>.<br/>
|
||||
If you're using multiple exchange sessions, you might need to custom the session name. <br/>
|
||||
This is for advanced users.
|
||||
</FormHelperText>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12}>
|
||||
<TextField id="key" name="api_key" label="API Key"
|
||||
fullWidth
|
||||
required
|
||||
onChange={(event) => {
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12}>
|
||||
<TextField id="secret" name="api_secret" label="API Secret"
|
||||
fullWidth
|
||||
required
|
||||
onChange={(event) => {
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<div className={classes.buttons}>
|
||||
<Button
|
||||
onClick={() => {
|
||||
if (onBack) {
|
||||
onBack();
|
||||
}
|
||||
}}>
|
||||
Back
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={handleAdd}
|
||||
>
|
||||
Add
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{
|
||||
response ? response.error ? (
|
||||
<Box m={2}>
|
||||
<Alert severity="error">{response.error}</Alert>
|
||||
</Box>
|
||||
) : response.success ? (
|
||||
<Box m={2}>
|
||||
<Alert severity="success">Exchange Session Added</Alert>
|
||||
</Box>
|
||||
) : null : null
|
||||
}
|
||||
|
||||
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
|
@ -10,7 +10,6 @@ import PowerIcon from '@material-ui/icons/Power';
|
|||
|
||||
import {makeStyles} from '@material-ui/core/styles';
|
||||
import {querySessions} from "../api/bbgo";
|
||||
import {Power} from "@material-ui/icons";
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
formControl: {
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
"classnames": "^2.2.6",
|
||||
"next": "^10.0.5",
|
||||
"react": "^17.0.1",
|
||||
"react-dom": "^17.0.1"
|
||||
"react-dom": "^17.0.1",
|
||||
"react-number-format": "^4.4.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^14.14.22",
|
||||
|
|
|
@ -11,6 +11,7 @@ import StepLabel from '@material-ui/core/StepLabel';
|
|||
import ConfigureDatabaseForm from "../../components/ConfigureDatabaseForm";
|
||||
import AddExchangeSessionForm from "../../components/AddExchangeSessionForm";
|
||||
import ReviewSessions from "../../components/ReviewSessions";
|
||||
import ConfigureGridStrategyForm from "../../components/ConfigureGridStrategyForm";
|
||||
|
||||
import PlainLayout from '../../layouts/PlainLayout';
|
||||
|
||||
|
@ -20,7 +21,7 @@ const useStyles = makeStyles((theme) => ({
|
|||
},
|
||||
}));
|
||||
|
||||
const steps = ['Configure Database', 'Add Exchange Session', 'Configure Strategy', 'Restart BBGO'];
|
||||
const steps = ['Configure Database', 'Add Exchange Session', 'Review Sessions', 'Configure Strategy', 'Save Config and Restart'];
|
||||
|
||||
function getStepContent(step, setActiveStep) {
|
||||
switch (step) {
|
||||
|
@ -41,6 +42,11 @@ function getStepContent(step, setActiveStep) {
|
|||
setActiveStep(3)
|
||||
}}/>
|
||||
case 3:
|
||||
return (
|
||||
<ConfigureGridStrategyForm />
|
||||
);
|
||||
|
||||
case 4:
|
||||
return;
|
||||
default:
|
||||
throw new Error('Unknown step');
|
||||
|
|
|
@ -4096,6 +4096,13 @@ react-motion@^0.5.2:
|
|||
prop-types "^15.5.8"
|
||||
raf "^3.1.0"
|
||||
|
||||
react-number-format@^4.4.4:
|
||||
version "4.4.4"
|
||||
resolved "https://registry.yarnpkg.com/react-number-format/-/react-number-format-4.4.4.tgz#2a7f50be404f990ec15855cc6babfeae1be16351"
|
||||
integrity sha512-/MuF1GOs1Z0xBaQie8+TTqCxUTT8xxjc6RqIFVWcWB6FM8GNIenSh2ayzN6Y1J2WMcXUDVwMdDXjweHKVjXm/w==
|
||||
dependencies:
|
||||
prop-types "^15.7.2"
|
||||
|
||||
react-refresh@0.8.3:
|
||||
version "0.8.3"
|
||||
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f"
|
||||
|
|
Loading…
Reference in New Issue
Block a user