mirror of
https://github.com/FxPouya/FxMathQuantWebApp.git
synced 2026-08-04 13:57:43 +00:00
Add files via upload
This commit is contained in:
+152
@@ -0,0 +1,152 @@
|
||||
/**
|
||||
* Strategy Class - Represents a trading strategy with rules and parameters
|
||||
*/
|
||||
class Strategy {
|
||||
constructor() {
|
||||
this.rules = [];
|
||||
this.atrPeriod = 20;
|
||||
this.slMultiplier = 2.0;
|
||||
this.tpMultiplier = 3.0;
|
||||
this.closeAtOpposite = false; // Disable to allow independent BUY/SELL signals
|
||||
this.fitness = 0;
|
||||
this.metrics = {};
|
||||
this.id = this.generateId();
|
||||
}
|
||||
|
||||
generateId() {
|
||||
return 'strategy_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate random trading rules
|
||||
*/
|
||||
generateRandomRules(count, shiftRange) {
|
||||
const minRules = count[0] || 3;
|
||||
const maxRules = count[1] || 8;
|
||||
const numRules = Math.floor(Math.random() * (maxRules - minRules + 1)) + minRules;
|
||||
|
||||
for (let i = 0; i < numRules; i++) {
|
||||
this.rules.push(this.generateRule(shiftRange));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a single random rule
|
||||
*/
|
||||
generateRule(shiftRange) {
|
||||
const priceTypes = ['open', 'high', 'low', 'close'];
|
||||
const operators = ['>', '<', '>=', '<='];
|
||||
|
||||
const minShift = shiftRange[0] || 1;
|
||||
const maxShift = shiftRange[1] || 10;
|
||||
|
||||
// 70% simple rules, 30% arithmetic rules
|
||||
if (Math.random() < 0.7) {
|
||||
// Simple rule: CLOSE[1] > OPEN[2]
|
||||
return {
|
||||
type: 'simple',
|
||||
left: {
|
||||
price: priceTypes[Math.floor(Math.random() * 4)],
|
||||
shift: Math.floor(Math.random() * (maxShift - minShift + 1)) + minShift
|
||||
},
|
||||
operator: operators[Math.floor(Math.random() * 4)],
|
||||
right: {
|
||||
price: priceTypes[Math.floor(Math.random() * 4)],
|
||||
shift: Math.floor(Math.random() * (maxShift - minShift + 1)) + minShift
|
||||
}
|
||||
};
|
||||
} else {
|
||||
// Arithmetic rule: (HIGH[1] + LOW[1]) > (CLOSE[2] * 1.01)
|
||||
const arithmeticOps = ['+', '-', '*'];
|
||||
const multipliers = [0.99, 1.01, 1.02, 0.98];
|
||||
|
||||
return {
|
||||
type: 'arithmetic',
|
||||
left: {
|
||||
price1: priceTypes[Math.floor(Math.random() * 4)],
|
||||
shift1: Math.floor(Math.random() * (maxShift - minShift + 1)) + minShift,
|
||||
op: arithmeticOps[Math.floor(Math.random() * 3)],
|
||||
price2: priceTypes[Math.floor(Math.random() * 4)],
|
||||
shift2: Math.floor(Math.random() * (maxShift - minShift + 1)) + minShift
|
||||
},
|
||||
operator: operators[Math.floor(Math.random() * 4)],
|
||||
right: {
|
||||
price: priceTypes[Math.floor(Math.random() * 4)],
|
||||
shift: Math.floor(Math.random() * (maxShift - minShift + 1)) + minShift,
|
||||
multiplier: multipliers[Math.floor(Math.random() * 4)]
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Randomize ATR and SL/TP parameters
|
||||
*/
|
||||
randomizeParameters() {
|
||||
this.atrPeriod = Math.floor(Math.random() * 31) + 10; // 10-40
|
||||
this.slMultiplier = (Math.random() * 3) + 1; // 1.0-4.0
|
||||
this.tpMultiplier = this.slMultiplier + (Math.random() * 5) + 0.5; // SL + 0.5 to 5.5
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a deep copy of the strategy
|
||||
*/
|
||||
copy() {
|
||||
const newStrategy = new Strategy();
|
||||
newStrategy.rules = JSON.parse(JSON.stringify(this.rules));
|
||||
newStrategy.atrPeriod = this.atrPeriod;
|
||||
newStrategy.slMultiplier = this.slMultiplier;
|
||||
newStrategy.tpMultiplier = this.tpMultiplier;
|
||||
newStrategy.closeAtOpposite = this.closeAtOpposite;
|
||||
newStrategy.metrics = this.metrics ? JSON.parse(JSON.stringify(this.metrics)) : {};
|
||||
newStrategy.fitness = this.fitness || 0;
|
||||
return newStrategy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert rules to human-readable format
|
||||
*/
|
||||
getRulesText() {
|
||||
return this.rules.map((rule, index) => {
|
||||
if (rule.type === 'simple') {
|
||||
return `${index + 1}. ${rule.left.price.toUpperCase()}[${rule.left.shift}] ${rule.operator} ${rule.right.price.toUpperCase()}[${rule.right.shift}]`;
|
||||
} else {
|
||||
return `${index + 1}. (${rule.left.price1.toUpperCase()}[${rule.left.shift1}] ${rule.left.op} ${rule.left.price2.toUpperCase()}[${rule.left.shift2}]) ${rule.operator} (${rule.right.price.toUpperCase()}[${rule.right.shift}] * ${rule.right.multiplier})`;
|
||||
}
|
||||
}).join('\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* Export to JSON
|
||||
*/
|
||||
toJSON() {
|
||||
return {
|
||||
id: this.id,
|
||||
rules: this.rules,
|
||||
parameters: {
|
||||
atr_period: this.atrPeriod,
|
||||
sl_multiplier: this.slMultiplier,
|
||||
tp_multiplier: this.tpMultiplier,
|
||||
close_at_opposite: this.closeAtOpposite
|
||||
},
|
||||
performance: this.metrics,
|
||||
fitness: this.fitness
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Import from JSON
|
||||
*/
|
||||
static fromJSON(json) {
|
||||
const strategy = new Strategy();
|
||||
strategy.id = json.id;
|
||||
strategy.rules = json.rules;
|
||||
strategy.atrPeriod = json.parameters.atr_period;
|
||||
strategy.slMultiplier = json.parameters.sl_multiplier;
|
||||
strategy.tpMultiplier = json.parameters.tp_multiplier;
|
||||
strategy.closeAtOpposite = json.parameters.close_at_opposite || false;
|
||||
strategy.metrics = json.performance || {};
|
||||
strategy.fitness = json.fitness || 0;
|
||||
return strategy;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user