Merge pull request #13 from nikolabjelo/develop
Switching to trading protocol 0.1
This commit is contained in:
33 files changed
+244
-1183
No files matched your search
@@ -5,5 +5,6 @@ module.exports = {
|
||||
'max-len': ['error', 140, 2],
|
||||
'no-underscore-dangle': 'off',
|
||||
'no-param-reassign': 'off',
|
||||
'import/no-cycle': 'off',
|
||||
}
|
||||
};
|
||||
Generated
+5
@@ -3587,6 +3587,11 @@
|
||||
"uuid": "^3.1.0"
|
||||
}
|
||||
},
|
||||
"graphql-type-json": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/graphql-type-json/-/graphql-type-json-0.3.0.tgz",
|
||||
"integrity": "sha512-lnxg5HiB95yxy+/5cDKtP6pZo0zgntsOmqsjeCBXFGJ4YoMF3+1YaSEKWJntNTu+VsAm3zf6lPxFpp1kxzofLA=="
|
||||
},
|
||||
"graphql-upload": {
|
||||
"version": "8.0.6",
|
||||
"resolved": "https://registry.npmjs.org/graphql-upload/-/graphql-upload-8.0.6.tgz",
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
"dotenv": "^6.0.0",
|
||||
"express": "^4.16.3",
|
||||
"graphql": "^0.13.2",
|
||||
"graphql-type-json": "^0.3.0",
|
||||
"mongoose": "^5.3.4"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'dotenv/config';
|
||||
import mongoose from 'mongoose';
|
||||
|
||||
mongoose.connect(process.env.MONGO_URL, { useNewUrlParser: true })
|
||||
mongoose.connect(process.env.MONGO_URL, { useNewUrlParser: true });
|
||||
mongoose.set('useCreateIndex', true);
|
||||
mongoose.set('useFindAndModify', false);
|
||||
mongoose.Promise = global.Promise;
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
export class AuthentificationError extends Error {
|
||||
code = 401
|
||||
|
||||
message = 'Autentification not found, you have to be authentificated to perform this action'
|
||||
}
|
||||
|
||||
export class DatabaseError extends Error {
|
||||
code = 404
|
||||
|
||||
message = `Ressource not found : ${this.message}`
|
||||
}
|
||||
|
||||
export class WrongArgumentsError extends Error {
|
||||
code = 400
|
||||
|
||||
message = `Wrong arguments : ${this.message}`
|
||||
}
|
||||
|
||||
export class ServiceUnavailableError extends Error {
|
||||
code = 503
|
||||
|
||||
message = `At least one service is unresponding ${this.message}`
|
||||
}
|
||||
@@ -1,351 +0,0 @@
|
||||
import mongoose, { Schema } from 'mongoose';
|
||||
|
||||
const strategySchema = new Schema(
|
||||
{
|
||||
fbSlug: {
|
||||
type: String,
|
||||
required: true,
|
||||
unique: true,
|
||||
dropDups: true,
|
||||
},
|
||||
subStrategies: [{
|
||||
active: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
default: true,
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
entryPoint: {
|
||||
situations: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
conditions: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
code: {
|
||||
type: String,
|
||||
default: 'false',
|
||||
},
|
||||
}],
|
||||
}],
|
||||
},
|
||||
exitPoint: {
|
||||
situations: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
conditions: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
code: {
|
||||
type: String,
|
||||
default: 'false',
|
||||
},
|
||||
}],
|
||||
}],
|
||||
},
|
||||
sellPoint: {
|
||||
situations: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
conditions: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
code: {
|
||||
type: String,
|
||||
default: 'false',
|
||||
},
|
||||
}],
|
||||
}],
|
||||
},
|
||||
buyPoint: {
|
||||
situations: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
conditions: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
code: {
|
||||
type: String,
|
||||
default: 'false',
|
||||
},
|
||||
}],
|
||||
}],
|
||||
},
|
||||
stopLoss: {
|
||||
phases: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
code: {
|
||||
type: String,
|
||||
default: 'false',
|
||||
},
|
||||
situations: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
conditions: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
code: {
|
||||
type: String,
|
||||
default: 'false',
|
||||
},
|
||||
}],
|
||||
}],
|
||||
}],
|
||||
},
|
||||
buyOrder: {
|
||||
phases: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
code: {
|
||||
type: String,
|
||||
default: 'false',
|
||||
},
|
||||
situations: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
conditions: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
code: {
|
||||
type: String,
|
||||
default: 'false',
|
||||
},
|
||||
}],
|
||||
}],
|
||||
}],
|
||||
},
|
||||
sellOrder: {
|
||||
phases: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
code: {
|
||||
type: String,
|
||||
default: 'false',
|
||||
},
|
||||
situations: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
conditions: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
code: {
|
||||
type: String,
|
||||
default: 'false',
|
||||
},
|
||||
}],
|
||||
}],
|
||||
}],
|
||||
},
|
||||
}],
|
||||
history: [{
|
||||
updatedAt: Date,
|
||||
subStrategies: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
entryPoint: {
|
||||
situations: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
conditions: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
code: {
|
||||
type: String,
|
||||
default: 'false',
|
||||
},
|
||||
}],
|
||||
}],
|
||||
},
|
||||
exitPoint: {
|
||||
situations: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
conditions: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
code: {
|
||||
type: String,
|
||||
default: 'false',
|
||||
},
|
||||
}],
|
||||
}],
|
||||
},
|
||||
sellPoint: {
|
||||
situations: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
conditions: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
code: {
|
||||
type: String,
|
||||
default: 'false',
|
||||
},
|
||||
}],
|
||||
}],
|
||||
},
|
||||
buyPoint: {
|
||||
situations: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
conditions: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
code: {
|
||||
type: String,
|
||||
default: 'false',
|
||||
},
|
||||
}],
|
||||
}],
|
||||
},
|
||||
stopLoss: {
|
||||
phases: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
code: {
|
||||
type: String,
|
||||
default: 'false',
|
||||
},
|
||||
situations: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
conditions: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
code: {
|
||||
type: String,
|
||||
default: 'false',
|
||||
},
|
||||
}],
|
||||
}],
|
||||
}],
|
||||
},
|
||||
buyOrder: {
|
||||
phases: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
code: {
|
||||
type: String,
|
||||
default: 'false',
|
||||
},
|
||||
situations: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
conditions: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
code: {
|
||||
type: String,
|
||||
default: 'false',
|
||||
},
|
||||
}],
|
||||
}],
|
||||
}],
|
||||
},
|
||||
sellOrder: {
|
||||
phases: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
code: {
|
||||
type: String,
|
||||
default: 'false',
|
||||
},
|
||||
situations: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
conditions: [{
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
code: {
|
||||
type: String,
|
||||
default: 'false',
|
||||
},
|
||||
}],
|
||||
}],
|
||||
}],
|
||||
},
|
||||
}],
|
||||
}],
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
},
|
||||
);
|
||||
|
||||
const Strategy = mongoose.model('Strategy', strategySchema);
|
||||
|
||||
export default Strategy;
|
||||
@@ -0,0 +1,54 @@
|
||||
import mongoose, { Schema } from 'mongoose';
|
||||
|
||||
const tradingSystemSchema = new Schema(
|
||||
{
|
||||
fbSlug: {
|
||||
type: String,
|
||||
required: true,
|
||||
unique: true,
|
||||
dropDups: true,
|
||||
},
|
||||
strategies: [{
|
||||
active: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
default: true,
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
filter: Object,
|
||||
triggerStage: Object,
|
||||
openStage: Object,
|
||||
manageStage: Object,
|
||||
closeStage: Object,
|
||||
}],
|
||||
history: [{
|
||||
updatedAt: Date,
|
||||
strategies: [{
|
||||
active: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
default: true,
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
filter: Object,
|
||||
triggerStage: Object,
|
||||
openStage: Object,
|
||||
manageStage: Object,
|
||||
closeStage: Object,
|
||||
}],
|
||||
}],
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
},
|
||||
);
|
||||
|
||||
const TradingSystem = mongoose.model('TradingSystem', tradingSystemSchema);
|
||||
|
||||
export default TradingSystem;
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
import Strategy from './Strategy';
|
||||
import TradingSystem from './TradingSystem';
|
||||
|
||||
export {
|
||||
Strategy,
|
||||
TradingSystem,
|
||||
};
|
||||
@@ -1,41 +0,0 @@
|
||||
import {
|
||||
GraphQLNonNull,
|
||||
GraphQLString,
|
||||
} from 'graphql';
|
||||
import { StrategyType } from '../types';
|
||||
import { Strategy } from '../../models';
|
||||
import { StrategyInputType } from '../types/input';
|
||||
import defaultStrategy from '../../templates/strategyTemplate';
|
||||
|
||||
export const args = {
|
||||
fbSlug: { type: new GraphQLNonNull(GraphQLString) },
|
||||
strategy: { type: StrategyInputType },
|
||||
};
|
||||
|
||||
const resolve = (parent, { fbSlug, strategy }) => {
|
||||
if (strategy === undefined) {
|
||||
strategy = defaultStrategy;
|
||||
}
|
||||
strategy.fbSlug = fbSlug;
|
||||
const newStrategy = new Strategy(strategy);
|
||||
|
||||
return new Promise((res, rej) => {
|
||||
newStrategy.save((err) => {
|
||||
if (err) {
|
||||
rej(err);
|
||||
return;
|
||||
}
|
||||
res(newStrategy);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const mutation = {
|
||||
createStrategy: {
|
||||
type: StrategyType,
|
||||
args,
|
||||
resolve,
|
||||
},
|
||||
};
|
||||
|
||||
export default mutation;
|
||||
@@ -0,0 +1,41 @@
|
||||
import {
|
||||
GraphQLNonNull,
|
||||
GraphQLString,
|
||||
} from 'graphql';
|
||||
import { TradingSystemType } from '../types';
|
||||
import { TradingSystem } from '../../models';
|
||||
import { TradingSystemInputType } from '../types/input';
|
||||
import defaultTradingSystem from '../../templates/tradingSystemTemplate';
|
||||
|
||||
export const args = {
|
||||
fbSlug: { type: new GraphQLNonNull(GraphQLString) },
|
||||
tradingSystem: { type: TradingSystemInputType },
|
||||
};
|
||||
|
||||
const resolve = (parent, { fbSlug, tradingSystem }) => {
|
||||
if (tradingSystem === undefined) {
|
||||
tradingSystem = defaultTradingSystem;
|
||||
}
|
||||
tradingSystem.fbSlug = fbSlug;
|
||||
const newTradingSystem = new TradingSystem(tradingSystem);
|
||||
|
||||
return new Promise((res, rej) => {
|
||||
newTradingSystem.save((err) => {
|
||||
if (err) {
|
||||
rej(err);
|
||||
return;
|
||||
}
|
||||
res(newTradingSystem);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const mutation = {
|
||||
createTradingSystem: {
|
||||
type: TradingSystemType,
|
||||
args,
|
||||
resolve,
|
||||
},
|
||||
};
|
||||
|
||||
export default mutation;
|
||||
@@ -1,43 +0,0 @@
|
||||
import {
|
||||
GraphQLNonNull,
|
||||
GraphQLID,
|
||||
} from 'graphql';
|
||||
import { StrategyType } from '../types';
|
||||
import { Strategy } from '../../models';
|
||||
import { StrategyInputType } from '../types/input';
|
||||
|
||||
const args = {
|
||||
id: { type: new GraphQLNonNull(GraphQLID) },
|
||||
strategy: { type: new GraphQLNonNull(StrategyInputType) },
|
||||
};
|
||||
|
||||
const resolve = (parent, { id: _id, strategy: editedStrategy }) => new Promise((res, rej) => {
|
||||
Strategy.findOne({ _id }).exec((err, strategy) => {
|
||||
if (err) {
|
||||
rej(err);
|
||||
return;
|
||||
}
|
||||
strategy.history.push({
|
||||
updatedAt: strategy.updatedAt,
|
||||
subStrategies: strategy.subStrategies,
|
||||
});
|
||||
strategy.subStrategies = editedStrategy.subStrategies;
|
||||
strategy.save((error) => {
|
||||
if (error) {
|
||||
rej(error);
|
||||
return;
|
||||
}
|
||||
res(strategy);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const mutation = {
|
||||
editStrategy: {
|
||||
type: StrategyType,
|
||||
args,
|
||||
resolve,
|
||||
},
|
||||
};
|
||||
|
||||
export default mutation;
|
||||
@@ -0,0 +1,43 @@
|
||||
import {
|
||||
GraphQLNonNull,
|
||||
GraphQLID,
|
||||
} from 'graphql';
|
||||
import { TradingSystemType } from '../types';
|
||||
import { TradingSystem } from '../../models';
|
||||
import { TradingSystemInputType } from '../types/input';
|
||||
|
||||
const args = {
|
||||
id: { type: new GraphQLNonNull(GraphQLID) },
|
||||
tradingSystem: { type: new GraphQLNonNull(TradingSystemInputType) },
|
||||
};
|
||||
|
||||
const resolve = (parent, { id: _id, tradingSystem: editedTradingSystem }) => new Promise((res, rej) => {
|
||||
TradingSystem.findOne({ _id }).exec((err, tradingSystem) => {
|
||||
if (err) {
|
||||
rej(err);
|
||||
return;
|
||||
}
|
||||
tradingSystem.history.push({
|
||||
updatedAt: tradingSystem.updatedAt,
|
||||
strategies: tradingSystem.strategies,
|
||||
});
|
||||
tradingSystem.strategies = editedTradingSystem.strategies;
|
||||
tradingSystem.save((error) => {
|
||||
if (error) {
|
||||
rej(error);
|
||||
return;
|
||||
}
|
||||
res(tradingSystem);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const mutation = {
|
||||
editTradingSystem: {
|
||||
type: TradingSystemType,
|
||||
args,
|
||||
resolve,
|
||||
},
|
||||
};
|
||||
|
||||
export default mutation;
|
||||
@@ -2,14 +2,14 @@ import {
|
||||
GraphQLObjectType,
|
||||
} from 'graphql';
|
||||
|
||||
import CreateStrategyMutation from './CreateStrategy';
|
||||
import EditStrategyMutation from './EditStrategy';
|
||||
import CreateTradingSystemMutation from './CreateTradingSystem';
|
||||
import EditTradingSystemMutation from './EditTradingSystem';
|
||||
|
||||
const Mutation = new GraphQLObjectType({
|
||||
name: 'Mutation',
|
||||
fields: Object.assign(
|
||||
CreateStrategyMutation,
|
||||
EditStrategyMutation,
|
||||
CreateTradingSystemMutation,
|
||||
EditTradingSystemMutation,
|
||||
),
|
||||
});
|
||||
|
||||
|
||||
@@ -3,30 +3,30 @@ import {
|
||||
GraphQLString,
|
||||
} from 'graphql';
|
||||
import { DatabaseError } from '../../errors';
|
||||
import { StrategyType } from '../types';
|
||||
import { Strategy } from '../../models';
|
||||
import { TradingSystemType } from '../types';
|
||||
import { TradingSystem } from '../../models';
|
||||
|
||||
const args = {
|
||||
fbSlug: { type: new GraphQLNonNull(GraphQLString) },
|
||||
};
|
||||
|
||||
const resolve = (parent, { fbSlug }) => new Promise((res, rej) => {
|
||||
Strategy.findOne({ fbSlug }).exec((err, strategy) => {
|
||||
TradingSystem.findOne({ fbSlug }).exec((err, tradingSystem) => {
|
||||
if (err) {
|
||||
rej(err);
|
||||
return;
|
||||
}
|
||||
if (!strategy) {
|
||||
rej(new DatabaseError('None of the strategy are linked to that fbSlug'));
|
||||
if (!tradingSystem) {
|
||||
rej(new DatabaseError('None of the tradingSystem are linked to that fbSlug'));
|
||||
return;
|
||||
}
|
||||
res(strategy);
|
||||
res(tradingSystem);
|
||||
});
|
||||
});
|
||||
|
||||
const query = {
|
||||
strategyByFb: {
|
||||
type: StrategyType,
|
||||
tradingSystemByFb: {
|
||||
type: TradingSystemType,
|
||||
args,
|
||||
resolve,
|
||||
},
|
||||
@@ -2,12 +2,12 @@ import {
|
||||
GraphQLObjectType,
|
||||
} from 'graphql';
|
||||
|
||||
import StrategyByFbQuery from './StrategyByFB';
|
||||
import TradingSystemByFbQuery from './TradingSystemByFB';
|
||||
|
||||
const RootQuery = new GraphQLObjectType({
|
||||
name: 'RootQueryType',
|
||||
fields: Object.assign(
|
||||
StrategyByFbQuery,
|
||||
TradingSystemByFbQuery,
|
||||
),
|
||||
});
|
||||
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
import {
|
||||
GraphQLObjectType,
|
||||
GraphQLString,
|
||||
} from 'graphql';
|
||||
|
||||
const Type = new GraphQLObjectType({
|
||||
name: 'Condition',
|
||||
description: 'Condition definition',
|
||||
fields: () => ({
|
||||
name: { type: GraphQLString },
|
||||
code: { type: GraphQLString },
|
||||
}),
|
||||
});
|
||||
|
||||
export default Type;
|
||||
@@ -1,25 +0,0 @@
|
||||
import {
|
||||
GraphQLObjectType,
|
||||
GraphQLString,
|
||||
GraphQLList,
|
||||
} from 'graphql';
|
||||
import {
|
||||
SituationType,
|
||||
} from './index';
|
||||
|
||||
const Type = new GraphQLObjectType({
|
||||
name: 'Phase',
|
||||
description: 'Phase definition',
|
||||
fields: () => ({
|
||||
name: { type: GraphQLString },
|
||||
code: { type: GraphQLString },
|
||||
situations: {
|
||||
type: new GraphQLList(SituationType),
|
||||
resolve(parent) {
|
||||
return parent.situations;
|
||||
},
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
export default Type;
|
||||
@@ -1,24 +0,0 @@
|
||||
import {
|
||||
GraphQLObjectType,
|
||||
GraphQLString,
|
||||
GraphQLList,
|
||||
} from 'graphql';
|
||||
import {
|
||||
ConditionType,
|
||||
} from './index';
|
||||
|
||||
const Type = new GraphQLObjectType({
|
||||
name: 'Situation',
|
||||
description: 'Situation definition',
|
||||
fields: () => ({
|
||||
name: { type: GraphQLString },
|
||||
conditions: {
|
||||
type: new GraphQLList(ConditionType),
|
||||
resolve(parent) {
|
||||
return parent.conditions;
|
||||
},
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
export default Type;
|
||||
@@ -1,30 +1,21 @@
|
||||
import {
|
||||
GraphQLObjectType,
|
||||
GraphQLString,
|
||||
GraphQLList,
|
||||
GraphQLBoolean,
|
||||
GraphQLID,
|
||||
} from 'graphql';
|
||||
import {
|
||||
SubStrategyType,
|
||||
} from './index';
|
||||
import GraphQLJSON from 'graphql-type-json';
|
||||
|
||||
const Type = new GraphQLObjectType({
|
||||
name: 'Strategy',
|
||||
description: 'Everything you need to know about a strategy',
|
||||
description: 'Strategy composing a trading system',
|
||||
fields: () => ({
|
||||
id: { type: GraphQLID },
|
||||
fbSlug: { type: GraphQLString },
|
||||
subStrategies: {
|
||||
args: { activeOnly: { type: GraphQLBoolean } },
|
||||
type: new GraphQLList(SubStrategyType),
|
||||
resolve(parent, { activeOnly }) {
|
||||
if (activeOnly) {
|
||||
return parent.subStrategies.filter(subStrategy => subStrategy.active);
|
||||
}
|
||||
return parent.subStrategies;
|
||||
},
|
||||
},
|
||||
active: { type: GraphQLBoolean },
|
||||
name: { type: GraphQLString },
|
||||
filter: { type: GraphQLJSON },
|
||||
triggerStage: { type: GraphQLJSON },
|
||||
openStage: { type: GraphQLJSON },
|
||||
manageStage: { type: GraphQLJSON },
|
||||
closeStage: { type: GraphQLJSON },
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
import {
|
||||
GraphQLObjectType,
|
||||
GraphQLString,
|
||||
GraphQLBoolean,
|
||||
} from 'graphql';
|
||||
import {
|
||||
EntryPointType,
|
||||
ExitPointType,
|
||||
SellPointType,
|
||||
BuyPointType,
|
||||
StopLossType,
|
||||
BuyOrderType,
|
||||
SellOrderType,
|
||||
} from './index';
|
||||
|
||||
const Type = new GraphQLObjectType({
|
||||
name: 'SubStrategy',
|
||||
description: 'SubStrategy composing a strategy',
|
||||
fields: () => ({
|
||||
active: { type: GraphQLBoolean },
|
||||
name: { type: GraphQLString },
|
||||
entryPoint: {
|
||||
type: EntryPointType,
|
||||
resolve(parent) {
|
||||
return parent.entryPoint;
|
||||
},
|
||||
},
|
||||
exitPoint: {
|
||||
type: ExitPointType,
|
||||
resolve(parent) {
|
||||
return parent.exitPoint;
|
||||
},
|
||||
},
|
||||
sellPoint: {
|
||||
type: SellPointType,
|
||||
resolve(parent) {
|
||||
return parent.sellPoint;
|
||||
},
|
||||
},
|
||||
buyPoint: {
|
||||
type: BuyPointType,
|
||||
resolve(parent) {
|
||||
return parent.buyPoint;
|
||||
},
|
||||
},
|
||||
stopLoss: {
|
||||
type: StopLossType,
|
||||
resolve(parent) {
|
||||
return parent.stopLoss;
|
||||
},
|
||||
},
|
||||
buyOrder: {
|
||||
type: BuyOrderType,
|
||||
resolve(parent) {
|
||||
return parent.buyOrder;
|
||||
},
|
||||
},
|
||||
sellOrder: {
|
||||
type: SellOrderType,
|
||||
resolve(parent) {
|
||||
return parent.sellOrder;
|
||||
},
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
export default Type;
|
||||
@@ -1,113 +0,0 @@
|
||||
import {
|
||||
GraphQLObjectType,
|
||||
GraphQLList,
|
||||
} from 'graphql';
|
||||
import {
|
||||
SituationType,
|
||||
PhaseType,
|
||||
} from './index';
|
||||
|
||||
// SituationBased
|
||||
|
||||
const EntryPointType = new GraphQLObjectType({
|
||||
name: 'EntryPoint',
|
||||
description: 'EntryPoint definition',
|
||||
fields: () => ({
|
||||
situations: {
|
||||
type: new GraphQLList(SituationType),
|
||||
resolve(parent) {
|
||||
return parent.situations;
|
||||
},
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
const ExitPointType = new GraphQLObjectType({
|
||||
name: 'ExitPoint',
|
||||
description: 'ExitPoint definition',
|
||||
fields: () => ({
|
||||
situations: {
|
||||
type: new GraphQLList(SituationType),
|
||||
resolve(parent) {
|
||||
return parent.situations;
|
||||
},
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
const SellPointType = new GraphQLObjectType({
|
||||
name: 'SellPoint',
|
||||
description: 'SellPoint definition',
|
||||
fields: () => ({
|
||||
situations: {
|
||||
type: new GraphQLList(SituationType),
|
||||
resolve(parent) {
|
||||
return parent.situations;
|
||||
},
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
const BuyPointType = new GraphQLObjectType({
|
||||
name: 'BuyPoint',
|
||||
description: 'BuyPoint definition',
|
||||
fields: () => ({
|
||||
situations: {
|
||||
type: new GraphQLList(SituationType),
|
||||
resolve(parent) {
|
||||
return parent.situations;
|
||||
},
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
// PhaseBased
|
||||
|
||||
const StopLossType = new GraphQLObjectType({
|
||||
name: 'StopLoss',
|
||||
description: 'StopLoss definition',
|
||||
fields: () => ({
|
||||
phases: {
|
||||
type: new GraphQLList(PhaseType),
|
||||
resolve(parent) {
|
||||
return parent.phases;
|
||||
},
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
const BuyOrderType = new GraphQLObjectType({
|
||||
name: 'BuyOrder',
|
||||
description: 'BuyOrder definition',
|
||||
fields: () => ({
|
||||
phases: {
|
||||
type: new GraphQLList(PhaseType),
|
||||
resolve(parent) {
|
||||
return parent.phases;
|
||||
},
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
const SellOrderType = new GraphQLObjectType({
|
||||
name: 'SellOrder',
|
||||
description: 'SellOrder definition',
|
||||
fields: () => ({
|
||||
phases: {
|
||||
type: new GraphQLList(PhaseType),
|
||||
resolve(parent) {
|
||||
return parent.phases;
|
||||
},
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
export {
|
||||
EntryPointType,
|
||||
ExitPointType,
|
||||
SellPointType,
|
||||
BuyPointType,
|
||||
StopLossType,
|
||||
BuyOrderType,
|
||||
SellOrderType,
|
||||
};
|
||||
@@ -0,0 +1,31 @@
|
||||
import {
|
||||
GraphQLObjectType,
|
||||
GraphQLString,
|
||||
GraphQLList,
|
||||
GraphQLBoolean,
|
||||
GraphQLID,
|
||||
} from 'graphql';
|
||||
import {
|
||||
StrategyType,
|
||||
} from './index';
|
||||
|
||||
const Type = new GraphQLObjectType({
|
||||
name: 'TradingSystem',
|
||||
description: 'Everything you need to know about a trading system',
|
||||
fields: () => ({
|
||||
id: { type: GraphQLID },
|
||||
fbSlug: { type: GraphQLString },
|
||||
strategies: {
|
||||
args: { activeOnly: { type: GraphQLBoolean } },
|
||||
type: new GraphQLList(StrategyType),
|
||||
resolve(parent, { activeOnly }) {
|
||||
if (activeOnly) {
|
||||
return parent.strategies.filter(strategy => strategy.active);
|
||||
}
|
||||
return parent.strategies;
|
||||
},
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
export default Type;
|
||||
@@ -1,29 +1,7 @@
|
||||
import TradingSystemType from './TradingSystem';
|
||||
import StrategyType from './Strategy';
|
||||
import SubStrategyType from './SubStrategy';
|
||||
import ConditionType from './Condition';
|
||||
import SituationType from './Situation';
|
||||
import PhaseType from './Phase';
|
||||
import {
|
||||
EntryPointType,
|
||||
ExitPointType,
|
||||
SellPointType,
|
||||
BuyPointType,
|
||||
StopLossType,
|
||||
BuyOrderType,
|
||||
SellOrderType,
|
||||
} from './TheSevenMonolitics';
|
||||
|
||||
export {
|
||||
StrategyType,
|
||||
SubStrategyType,
|
||||
ConditionType,
|
||||
SituationType,
|
||||
PhaseType,
|
||||
EntryPointType,
|
||||
ExitPointType,
|
||||
SellPointType,
|
||||
BuyPointType,
|
||||
StopLossType,
|
||||
BuyOrderType,
|
||||
SellOrderType,
|
||||
TradingSystemType,
|
||||
};
|
||||
@@ -1,15 +0,0 @@
|
||||
import {
|
||||
GraphQLString,
|
||||
GraphQLInputObjectType,
|
||||
} from 'graphql';
|
||||
|
||||
const Type = new GraphQLInputObjectType({
|
||||
name: 'ConditionInput',
|
||||
description: 'Payload for condition input',
|
||||
fields: () => ({
|
||||
name: { type: GraphQLString },
|
||||
code: { type: GraphQLString },
|
||||
}),
|
||||
});
|
||||
|
||||
export default Type;
|
||||
@@ -1,18 +0,0 @@
|
||||
import {
|
||||
GraphQLString,
|
||||
GraphQLInputObjectType,
|
||||
GraphQLList,
|
||||
} from 'graphql';
|
||||
import { SituationInputType } from './index';
|
||||
|
||||
const Type = new GraphQLInputObjectType({
|
||||
name: 'PhaseInput',
|
||||
description: 'Payload for phase input',
|
||||
fields: () => ({
|
||||
name: { type: GraphQLString },
|
||||
code: { type: GraphQLString },
|
||||
situations: { type: new GraphQLList(SituationInputType) },
|
||||
}),
|
||||
});
|
||||
|
||||
export default Type;
|
||||
@@ -1,17 +0,0 @@
|
||||
import {
|
||||
GraphQLString,
|
||||
GraphQLInputObjectType,
|
||||
GraphQLList,
|
||||
} from 'graphql';
|
||||
import { ConditionInputType } from './index';
|
||||
|
||||
const Type = new GraphQLInputObjectType({
|
||||
name: 'SituationInput',
|
||||
description: 'Payload for situation input',
|
||||
fields: () => ({
|
||||
name: { type: GraphQLString },
|
||||
conditions: { type: new GraphQLList(ConditionInputType) },
|
||||
}),
|
||||
});
|
||||
|
||||
export default Type;
|
||||
@@ -1,14 +1,21 @@
|
||||
import {
|
||||
GraphQLString,
|
||||
GraphQLBoolean,
|
||||
GraphQLInputObjectType,
|
||||
GraphQLList,
|
||||
} from 'graphql';
|
||||
import { SubStrategyInputType } from './index';
|
||||
import GraphQLJSON from 'graphql-type-json';
|
||||
|
||||
const Type = new GraphQLInputObjectType({
|
||||
name: 'StrategyInput',
|
||||
description: 'Payload for strategy input',
|
||||
name: 'SubStrategyInput',
|
||||
description: 'Payload for subStrategy input',
|
||||
fields: () => ({
|
||||
subStrategies: { type: new GraphQLList(SubStrategyInputType) },
|
||||
active: { type: GraphQLBoolean },
|
||||
name: { type: GraphQLString },
|
||||
filter: { type: GraphQLJSON },
|
||||
triggerStage: { type: GraphQLJSON },
|
||||
openStage: { type: GraphQLJSON },
|
||||
manageStage: { type: GraphQLJSON },
|
||||
closeStage: { type: GraphQLJSON },
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
import {
|
||||
GraphQLString,
|
||||
GraphQLBoolean,
|
||||
GraphQLInputObjectType,
|
||||
} from 'graphql';
|
||||
import {
|
||||
EntryPointInputType,
|
||||
ExitPointInputType,
|
||||
SellPointInputType,
|
||||
BuyPointInputType,
|
||||
StopLossInputType,
|
||||
BuyOrderInputType,
|
||||
SellOrderInputType,
|
||||
} from './index';
|
||||
|
||||
const Type = new GraphQLInputObjectType({
|
||||
name: 'SubStrategyInput',
|
||||
description: 'Payload for subStrategy input',
|
||||
fields: () => ({
|
||||
active: { type: GraphQLBoolean },
|
||||
name: { type: GraphQLString },
|
||||
entryPoint: { type: EntryPointInputType },
|
||||
exitPoint: { type: ExitPointInputType },
|
||||
sellPoint: { type: SellPointInputType },
|
||||
buyPoint: { type: BuyPointInputType },
|
||||
stopLoss: { type: StopLossInputType },
|
||||
buyOrder: { type: BuyOrderInputType },
|
||||
sellOrder: { type: SellOrderInputType },
|
||||
}),
|
||||
});
|
||||
|
||||
export default Type;
|
||||
@@ -1,75 +0,0 @@
|
||||
import {
|
||||
GraphQLInputObjectType,
|
||||
GraphQLList,
|
||||
} from 'graphql';
|
||||
import { SituationInputType, PhaseInputType } from './index';
|
||||
|
||||
// SituationBased
|
||||
|
||||
const EntryPointInputType = new GraphQLInputObjectType({
|
||||
name: 'EntryPointInput',
|
||||
description: 'Payload for entryPoint input',
|
||||
fields: () => ({
|
||||
situations: { type: new GraphQLList(SituationInputType) },
|
||||
}),
|
||||
});
|
||||
|
||||
const ExitPointInputType = new GraphQLInputObjectType({
|
||||
name: 'ExitPointInput',
|
||||
description: 'Payload for exitPoint input',
|
||||
fields: () => ({
|
||||
situations: { type: new GraphQLList(SituationInputType) },
|
||||
}),
|
||||
});
|
||||
|
||||
const SellPointInputType = new GraphQLInputObjectType({
|
||||
name: 'SellPointInput',
|
||||
description: 'Payload for sellPoint input',
|
||||
fields: () => ({
|
||||
situations: { type: new GraphQLList(SituationInputType) },
|
||||
}),
|
||||
});
|
||||
|
||||
const BuyPointInputType = new GraphQLInputObjectType({
|
||||
name: 'BuyPointInput',
|
||||
description: 'Payload for buyPoint input',
|
||||
fields: () => ({
|
||||
situations: { type: new GraphQLList(SituationInputType) },
|
||||
}),
|
||||
});
|
||||
|
||||
// PhaseBased
|
||||
|
||||
const StopLossInputType = new GraphQLInputObjectType({
|
||||
name: 'StopLossTypeInput',
|
||||
description: 'Payload for stopLossType input',
|
||||
fields: () => ({
|
||||
phases: { type: new GraphQLList(PhaseInputType) },
|
||||
}),
|
||||
});
|
||||
|
||||
const BuyOrderInputType = new GraphQLInputObjectType({
|
||||
name: 'BuyOrderTypeInput',
|
||||
description: 'Payload for buyOrderType input',
|
||||
fields: () => ({
|
||||
phases: { type: new GraphQLList(PhaseInputType) },
|
||||
}),
|
||||
});
|
||||
|
||||
const SellOrderInputType = new GraphQLInputObjectType({
|
||||
name: 'SellOrderTypeInput',
|
||||
description: 'Payload for sellOrderType input',
|
||||
fields: () => ({
|
||||
phases: { type: new GraphQLList(PhaseInputType) },
|
||||
}),
|
||||
});
|
||||
|
||||
export {
|
||||
EntryPointInputType,
|
||||
ExitPointInputType,
|
||||
SellPointInputType,
|
||||
BuyPointInputType,
|
||||
StopLossInputType,
|
||||
BuyOrderInputType,
|
||||
SellOrderInputType,
|
||||
};
|
||||
@@ -0,0 +1,15 @@
|
||||
import {
|
||||
GraphQLInputObjectType,
|
||||
GraphQLList,
|
||||
} from 'graphql';
|
||||
import { StrategyInputType } from './index';
|
||||
|
||||
const Type = new GraphQLInputObjectType({
|
||||
name: 'TradingSystemInput',
|
||||
description: 'Payload for trading system input',
|
||||
fields: () => ({
|
||||
strategies: { type: new GraphQLList(StrategyInputType) },
|
||||
}),
|
||||
});
|
||||
|
||||
export default Type;
|
||||
@@ -1,29 +1,7 @@
|
||||
import TradingSystemInputType from './TradingSystem';
|
||||
import StrategyInputType from './Strategy';
|
||||
import SubStrategyInputType from './SubStrategy';
|
||||
import ConditionInputType from './Condition';
|
||||
import SituationInputType from './Situation';
|
||||
import PhaseInputType from './Phase';
|
||||
import {
|
||||
EntryPointInputType,
|
||||
ExitPointInputType,
|
||||
SellPointInputType,
|
||||
BuyPointInputType,
|
||||
StopLossInputType,
|
||||
BuyOrderInputType,
|
||||
SellOrderInputType,
|
||||
} from './TheSevenMonolitics';
|
||||
|
||||
export {
|
||||
TradingSystemInputType,
|
||||
StrategyInputType,
|
||||
SubStrategyInputType,
|
||||
ConditionInputType,
|
||||
SituationInputType,
|
||||
PhaseInputType,
|
||||
EntryPointInputType,
|
||||
ExitPointInputType,
|
||||
SellPointInputType,
|
||||
BuyPointInputType,
|
||||
StopLossInputType,
|
||||
BuyOrderInputType,
|
||||
SellOrderInputType,
|
||||
};
|
||||
@@ -1,259 +0,0 @@
|
||||
/* eslint-disable max-len */
|
||||
const strategy = {
|
||||
subStrategies: [
|
||||
{
|
||||
active: true,
|
||||
name: 'Trend Following',
|
||||
entryPoint: {
|
||||
situations: [
|
||||
{
|
||||
name: 'Price Collapsing',
|
||||
conditions: [
|
||||
{
|
||||
name: '%B Moving Average going down',
|
||||
code: "percentageBandwidth.previous.direction === 'down' && percentageBandwidth.direction === 'down'",
|
||||
},
|
||||
{
|
||||
name: '%B Bandwidth going up',
|
||||
code: 'percentageBandwidth.previous.previous.bandwidth < percentageBandwidth.previous.bandwidth && percentageBandwidth.previous.bandwidth < percentageBandwidth.bandwidth',
|
||||
},
|
||||
{
|
||||
name: 'Candles Min going down',
|
||||
code: 'candle.previous.previous.min > candle.previous.min && candle.previous.min > candle.min',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
exitPoint: {
|
||||
situations: [
|
||||
{
|
||||
name: 'Market Reversing',
|
||||
conditions: [
|
||||
{
|
||||
name: 'Close above Band Moving Average',
|
||||
code: 'candle.close > bollingerBand.movingAverage',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
sellPoint: {
|
||||
situations: [
|
||||
{
|
||||
name: 'Min below lower bollingerBand.',
|
||||
conditions: [
|
||||
{
|
||||
name: '3 Candles MIN below Lower Band',
|
||||
code: 'candle.previous.previous.min < bollingerBand.previous.previous.movingAverage - bollingerBand.previous.previous.deviation && candle.previous.min < bollingerBand.previous.movingAverage - bollingerBand.previous.deviation && candle.min < bollingerBand.movingAverage - bollingerBand.deviation',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
stopLoss: {
|
||||
phases: [
|
||||
{
|
||||
name: 'Following Sell Rate',
|
||||
code: 'newStopLoss = sellRate + sellRate * (stopLossPercentage - stopLossDecay) / 100',
|
||||
situations: [
|
||||
{
|
||||
name: 'Candle below Moving Average',
|
||||
conditions: [
|
||||
{
|
||||
name: 'Candle fully below Band Moving Average',
|
||||
code: 'candle.max < bollingerBand.movingAverage',
|
||||
},
|
||||
{
|
||||
name: 'Band Moving Average going down',
|
||||
code: "bollingerBand.direction === 'down'",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Above Bands Moving Average',
|
||||
code: 'newStopLoss = bollingerBand.movingAverage + bollingerBand.movingAverage * (stopLossPercentage - stopLossDecay) / 100',
|
||||
situations: [
|
||||
{
|
||||
name: 'Candle below Moving Average',
|
||||
conditions: [
|
||||
{
|
||||
name: 'Candle MAX below lower band',
|
||||
code: 'candle.max < bollingerBand.movingAverage - bollingerBand.deviation',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'At Bands Moving Average',
|
||||
code: 'newStopLoss = bollingerBand.movingAverage',
|
||||
situations: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
buyOrder: {
|
||||
phases: [
|
||||
{
|
||||
name: '12 times standard deviation',
|
||||
code: 'buyOrder = bollingerBand.movingAverage - bollingerBand.standardDeviation * 12',
|
||||
situations: [
|
||||
{
|
||||
name: 'Candle cut by lower band',
|
||||
conditions: [
|
||||
{
|
||||
name: 'Max above lower band',
|
||||
code: 'candle.max > bollingerBand.movingAverage - bollingerBand.deviation',
|
||||
},
|
||||
{
|
||||
name: 'MIN below lower band',
|
||||
code: 'candle.min < bollingerBand.movingAverage - bollingerBand.deviation',
|
||||
},
|
||||
{
|
||||
name: 'Band Moving Average going down',
|
||||
code: 'bollingerBand.previous.movingAverage > bollingerBand.movingAverage',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: '10 times standard deviation',
|
||||
code: 'buyOrder = bollingerBand.movingAverage - bollingerBand.standardDeviation * 10',
|
||||
situations: [
|
||||
{
|
||||
name: '%B starting to revert',
|
||||
conditions: [
|
||||
{
|
||||
name: '%B Moving Average going up',
|
||||
code: "percentageBandwidth.direction === 'up'",
|
||||
},
|
||||
{
|
||||
name: '%B Moving Average above 0',
|
||||
code: 'percentageBandwidth.movingAverage > 0',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: '4 times standard deviation',
|
||||
code: 'buyOrder = bollingerBand.movingAverage - bollingerBand.standardDeviation * 4',
|
||||
situations: [
|
||||
{
|
||||
name: '%B going down again',
|
||||
conditions: [
|
||||
{
|
||||
name: '%B Moving Average going down',
|
||||
code: "percentageBandwidth.direction === 'down'",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: '3 times standard deviation',
|
||||
code: 'buyOrder = bollingerBand.movingAverage - bollingerBand.standardDeviation * 3',
|
||||
situations: [
|
||||
{
|
||||
name: '%B going up and above 30',
|
||||
conditions: [
|
||||
{
|
||||
name: '%B Moving Average going up',
|
||||
code: "percentageBandwidth.direction === 'up'",
|
||||
},
|
||||
{
|
||||
name: '%B Moving Average above 30',
|
||||
code: 'percentageBandwidth.movingAverage > 30',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'At lower band',
|
||||
code: 'buyOrder = bollingerBand.movingAverage - bollingerBand.standardDeviation * 2',
|
||||
situations: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
active: true,
|
||||
name: 'Range Trading',
|
||||
entryPoint: {
|
||||
situations: [
|
||||
{
|
||||
name: 'Gentle Up Trend',
|
||||
conditions: [
|
||||
{
|
||||
name: 'Sub-Channel going up',
|
||||
code: "subChannel.direction === 'up'",
|
||||
},
|
||||
{
|
||||
name: 'Sub-Channel Side|Gentle|Medium',
|
||||
code: "subChannel.slope === 'Side' || subChannel.slope === 'Gentle' || subChannel.slope === 'Medium'",
|
||||
},
|
||||
{
|
||||
name: 'Candle Close above Lower Band',
|
||||
code: 'candle.close > bollingerBand.movingAverage + bollingerBand.deviation',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
exitPoint: {
|
||||
situations: [
|
||||
{
|
||||
name: 'Outside Sub-Channel',
|
||||
conditions: [
|
||||
{
|
||||
name: 'Going down or too Steep',
|
||||
code: "subChannel.direction === 'Down' || subChannel.slope === 'Steep' || subChannel.slope === 'Extreme'",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
sellPoint: {
|
||||
situations: [
|
||||
{
|
||||
name: 'Min below lower bollingerBand.',
|
||||
conditions: [
|
||||
{
|
||||
name: '%B Moving Average going down',
|
||||
code: 'percentageBandwidth.previous.movingAverage > percentageBandwidth.movingAverage',
|
||||
},
|
||||
{
|
||||
name: '%B Moving Average above 90',
|
||||
code: 'percentageBandwidth.previous.movingAverage > 90',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
stopLoss: {
|
||||
phases: [
|
||||
{
|
||||
name: 'Following Sell Rate',
|
||||
code: 'newStopLoss = sellRate + sellRate * (stopLossPercentage - stopLossDecay) / 100',
|
||||
situations: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
buyOrder: {
|
||||
phases: [
|
||||
{
|
||||
name: 'Between Band Moving Average and Lower Band',
|
||||
code: 'buyOrder = bollingerBand.movingAverage - bollingerBand.standardDeviation',
|
||||
situations: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default strategy;
|
||||
@@ -0,0 +1,7 @@
|
||||
/* eslint-disable max-len */
|
||||
const tradingSystem = {
|
||||
strategies: [
|
||||
],
|
||||
};
|
||||
|
||||
export default tradingSystem;
|
||||
Reference in new issue
Block a user