@tradejs/strategies 1.0.9 → 1.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +497 -40
- package/dist/index.d.ts +497 -40
- package/dist/index.js +30337 -21690
- package/dist/index.mjs +31530 -87
- package/package.json +7 -6
- package/dist/chunk-37ZWRG3W.mjs +0 -128
- package/dist/chunk-H4MHFD4B.mjs +0 -62
- package/dist/chunk-HEBXNMVQ.mjs +0 -48
- package/dist/chunk-IMLNXICX.mjs +0 -547
- package/dist/chunk-QVWMBYYM.mjs +0 -836
- package/dist/chunk-SOVTOGY4.mjs +0 -163
- package/dist/chunk-TDUTYEGH.mjs +0 -797
- package/dist/chunk-UK4YHD2E.mjs +0 -683
- package/dist/strategy-ABIO65CR.mjs +0 -209
- package/dist/strategy-D7H5J3C4.mjs +0 -348
- package/dist/strategy-HQIPCUOY.mjs +0 -399
- package/dist/strategy-JQIJILHQ.mjs +0 -5735
- package/dist/strategy-QEIPAPY4.mjs +0 -373
- package/dist/strategy-WYN4FZ5S.mjs +0 -613
- package/dist/strategy-XTUKPYPM.mjs +0 -11618
|
@@ -1,399 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
buildReverseTrendlineStructuralContext,
|
|
3
|
-
buildReverseTrendlineTimingContext,
|
|
4
|
-
config,
|
|
5
|
-
reverseTrendLineManifest,
|
|
6
|
-
toFiniteNumberOrNull
|
|
7
|
-
} from "./chunk-UK4YHD2E.mjs";
|
|
8
|
-
import "./chunk-HEBXNMVQ.mjs";
|
|
9
|
-
|
|
10
|
-
// src/ReverseTrendLine/strategy.ts
|
|
11
|
-
import { createStrategyRuntime } from "@tradejs/node/strategies";
|
|
12
|
-
|
|
13
|
-
// src/ReverseTrendLine/core.ts
|
|
14
|
-
import { round as round2 } from "@tradejs/core/math";
|
|
15
|
-
import { createTrendlineEngine } from "@tradejs/core/indicators";
|
|
16
|
-
|
|
17
|
-
// src/ReverseTrendLine/filters.ts
|
|
18
|
-
import { diffRel } from "@tradejs/core/math";
|
|
19
|
-
var MAX_CANDLE_VOLATILITY = 0.025;
|
|
20
|
-
var filterByVeryVolatility = (data) => {
|
|
21
|
-
const lastCandle = data[data.length - 1];
|
|
22
|
-
const prevCandle = data[data.length - 2];
|
|
23
|
-
if (!lastCandle || !prevCandle) {
|
|
24
|
-
return false;
|
|
25
|
-
}
|
|
26
|
-
const isVeryVolatility = diffRel(lastCandle.low, lastCandle.high) > MAX_CANDLE_VOLATILITY || diffRel(prevCandle.low, prevCandle.high) > MAX_CANDLE_VOLATILITY;
|
|
27
|
-
return !isVeryVolatility;
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
// src/ReverseTrendLine/figures.ts
|
|
31
|
-
var buildReverseTrendLineFigures = (bestLine) => ({
|
|
32
|
-
lines: [
|
|
33
|
-
{
|
|
34
|
-
id: bestLine.id,
|
|
35
|
-
kind: "trendline",
|
|
36
|
-
points: [...bestLine.points ?? []].sort(
|
|
37
|
-
(left, right) => left.timestamp - right.timestamp
|
|
38
|
-
),
|
|
39
|
-
color: bestLine.mode === "lows" ? "#22c55e" : "#f97316",
|
|
40
|
-
width: 2,
|
|
41
|
-
style: "solid"
|
|
42
|
-
}
|
|
43
|
-
],
|
|
44
|
-
points: [
|
|
45
|
-
{
|
|
46
|
-
id: `${bestLine.id}-points`,
|
|
47
|
-
kind: "trendline_points",
|
|
48
|
-
points: [...bestLine.points ?? [], ...bestLine.touches ?? []].sort(
|
|
49
|
-
(left, right) => left.timestamp - right.timestamp
|
|
50
|
-
),
|
|
51
|
-
color: "#ef4444",
|
|
52
|
-
radius: 4
|
|
53
|
-
}
|
|
54
|
-
]
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
// src/ReverseTrendLine/risk.ts
|
|
58
|
-
import { round } from "@tradejs/core/math";
|
|
59
|
-
var MIN_STOP_BUFFER_PCT = 0.1;
|
|
60
|
-
var LINE_BUFFER_ATR_FACTOR = 0.25;
|
|
61
|
-
var LINE_BUFFER_BASE_SL_FACTOR = 0.1;
|
|
62
|
-
var ATR_STOP_FLOOR_FACTOR = 0.65;
|
|
63
|
-
var MIN_STOP_LOSS_FACTOR = 0.8;
|
|
64
|
-
var MAX_STOP_LOSS_FACTOR = 2;
|
|
65
|
-
var clampNumber = (value, min, max) => Math.min(Math.max(value, min), max);
|
|
66
|
-
var getTimingStopFactor = (entryTiming) => {
|
|
67
|
-
if (entryTiming === "ready_follow_through") {
|
|
68
|
-
return 0.95;
|
|
69
|
-
}
|
|
70
|
-
return 1;
|
|
71
|
-
};
|
|
72
|
-
var getTimingTargetRiskRatio = ({
|
|
73
|
-
direction,
|
|
74
|
-
entryTiming
|
|
75
|
-
}) => {
|
|
76
|
-
if (direction === "LONG") {
|
|
77
|
-
return entryTiming === "ready_follow_through" ? 2.15 : 1.95;
|
|
78
|
-
}
|
|
79
|
-
return entryTiming === "ready_follow_through" ? 2.2 : 2;
|
|
80
|
-
};
|
|
81
|
-
var buildReverseTrendlineRiskPlan = ({
|
|
82
|
-
direction,
|
|
83
|
-
modeConfig,
|
|
84
|
-
structuralContext,
|
|
85
|
-
timingContext
|
|
86
|
-
}) => {
|
|
87
|
-
const baseStopLossDelta = modeConfig.SL;
|
|
88
|
-
const atrPct = structuralContext.atrPct ?? baseStopLossDelta;
|
|
89
|
-
const priceVsLinePctAbs = structuralContext.priceVsLinePctAbs ?? 0;
|
|
90
|
-
const rejectionStrengthPct = structuralContext.rejectionStrengthPct ?? 0;
|
|
91
|
-
const touches = structuralContext.touches ?? 0;
|
|
92
|
-
const distance = structuralContext.distance ?? null;
|
|
93
|
-
const lineBufferPct = Math.max(
|
|
94
|
-
atrPct * LINE_BUFFER_ATR_FACTOR,
|
|
95
|
-
baseStopLossDelta * LINE_BUFFER_BASE_SL_FACTOR,
|
|
96
|
-
MIN_STOP_BUFFER_PCT
|
|
97
|
-
);
|
|
98
|
-
const lineInvalidationPct = priceVsLinePctAbs + lineBufferPct;
|
|
99
|
-
const volatilityFloorPct = Math.max(
|
|
100
|
-
atrPct * ATR_STOP_FLOOR_FACTOR,
|
|
101
|
-
baseStopLossDelta * MIN_STOP_LOSS_FACTOR
|
|
102
|
-
);
|
|
103
|
-
let stopLossDelta = Math.max(lineInvalidationPct, volatilityFloorPct);
|
|
104
|
-
if (touches >= 6) {
|
|
105
|
-
stopLossDelta *= 0.95;
|
|
106
|
-
} else if (touches > 0 && touches <= 4) {
|
|
107
|
-
stopLossDelta *= 1.03;
|
|
108
|
-
}
|
|
109
|
-
if (distance != null && distance >= 400) {
|
|
110
|
-
stopLossDelta *= 1.05;
|
|
111
|
-
} else if (distance != null && distance <= 120) {
|
|
112
|
-
stopLossDelta *= 0.95;
|
|
113
|
-
}
|
|
114
|
-
if (rejectionStrengthPct >= 0.2) {
|
|
115
|
-
stopLossDelta *= 0.95;
|
|
116
|
-
}
|
|
117
|
-
stopLossDelta *= getTimingStopFactor(timingContext.entryTiming);
|
|
118
|
-
stopLossDelta = clampNumber(
|
|
119
|
-
stopLossDelta,
|
|
120
|
-
baseStopLossDelta * MIN_STOP_LOSS_FACTOR,
|
|
121
|
-
baseStopLossDelta * MAX_STOP_LOSS_FACTOR
|
|
122
|
-
);
|
|
123
|
-
let targetRiskRatio = getTimingTargetRiskRatio({
|
|
124
|
-
direction,
|
|
125
|
-
entryTiming: timingContext.entryTiming
|
|
126
|
-
});
|
|
127
|
-
if (touches >= 6) {
|
|
128
|
-
targetRiskRatio += 0.1;
|
|
129
|
-
}
|
|
130
|
-
if (distance != null && distance >= 120 && distance <= 350) {
|
|
131
|
-
targetRiskRatio += 0.05;
|
|
132
|
-
}
|
|
133
|
-
if (direction === "SHORT" && distance != null && distance > 500) {
|
|
134
|
-
targetRiskRatio -= 0.15;
|
|
135
|
-
}
|
|
136
|
-
if (direction === "LONG" && distance != null && distance > 500) {
|
|
137
|
-
targetRiskRatio -= 0.1;
|
|
138
|
-
}
|
|
139
|
-
const minTargetRiskRatio = modeConfig.minRiskRatio + 0.05;
|
|
140
|
-
const maxTargetRiskRatio = Math.max(modeConfig.TP / modeConfig.SL, minTargetRiskRatio) + 0.3;
|
|
141
|
-
targetRiskRatio = clampNumber(
|
|
142
|
-
targetRiskRatio,
|
|
143
|
-
minTargetRiskRatio,
|
|
144
|
-
maxTargetRiskRatio
|
|
145
|
-
);
|
|
146
|
-
return {
|
|
147
|
-
stopLossDelta: round(stopLossDelta, 3),
|
|
148
|
-
targetRiskRatio: round(targetRiskRatio, 2),
|
|
149
|
-
takeProfitDelta: round(stopLossDelta * targetRiskRatio, 3)
|
|
150
|
-
};
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
// src/ReverseTrendLine/core.ts
|
|
154
|
-
var buildReverseTrendlineSignalSeed = ({
|
|
155
|
-
direction,
|
|
156
|
-
currentPrice,
|
|
157
|
-
indicators,
|
|
158
|
-
bestLine,
|
|
159
|
-
currentCandle,
|
|
160
|
-
reverseTrendlineTiming
|
|
161
|
-
}) => ({
|
|
162
|
-
direction,
|
|
163
|
-
prices: { currentPrice },
|
|
164
|
-
indicators,
|
|
165
|
-
additionalIndicators: {
|
|
166
|
-
touches: Array.isArray(bestLine.touches) ? bestLine.touches.length + 2 : 2,
|
|
167
|
-
distance: bestLine.distance,
|
|
168
|
-
trendLine: bestLine,
|
|
169
|
-
...currentCandle ? { currentCandle } : {},
|
|
170
|
-
...reverseTrendlineTiming ? { reverseTrendlineTiming } : {}
|
|
171
|
-
},
|
|
172
|
-
figures: {
|
|
173
|
-
trendLine: bestLine
|
|
174
|
-
}
|
|
175
|
-
});
|
|
176
|
-
var isOpenPosition = (position) => Boolean(
|
|
177
|
-
position && typeof position.price === "number" && Number.isFinite(position.price) && typeof position.qty === "number" && Number.isFinite(position.qty) && position.qty > 0 && (position.direction === "LONG" || position.direction === "SHORT")
|
|
178
|
-
);
|
|
179
|
-
var getLinePriceAtNow = (line, timestamp) => {
|
|
180
|
-
if (!line || !Array.isArray(line.points) || line.points.length === 0) {
|
|
181
|
-
return null;
|
|
182
|
-
}
|
|
183
|
-
const sortedPoints = [...line.points].sort(
|
|
184
|
-
(left, right) => left.timestamp - right.timestamp
|
|
185
|
-
);
|
|
186
|
-
const first = sortedPoints[0];
|
|
187
|
-
const last = sortedPoints[sortedPoints.length - 1];
|
|
188
|
-
if (first.timestamp === last.timestamp) {
|
|
189
|
-
return last.value;
|
|
190
|
-
}
|
|
191
|
-
const slope = (last.value - first.value) / (last.timestamp - first.timestamp);
|
|
192
|
-
return first.value + slope * (timestamp - first.timestamp);
|
|
193
|
-
};
|
|
194
|
-
var buildReverseTrendlineCandidateContext = ({
|
|
195
|
-
line,
|
|
196
|
-
candle,
|
|
197
|
-
direction
|
|
198
|
-
}) => {
|
|
199
|
-
const currentLinePrice = getLinePriceAtNow(line, candle.timestamp);
|
|
200
|
-
const priceVsLinePct = currentLinePrice != null && currentLinePrice !== 0 ? (candle.close - currentLinePrice) / currentLinePrice * 100 : null;
|
|
201
|
-
const priceVsLinePctAbs = priceVsLinePct == null ? null : Math.abs(priceVsLinePct);
|
|
202
|
-
const lineTouchedNow = currentLinePrice != null && candle.low <= currentLinePrice && candle.high >= currentLinePrice;
|
|
203
|
-
const failedBounceBreak = direction === "LONG" ? priceVsLinePct != null && priceVsLinePct <= -0.35 : priceVsLinePct != null && priceVsLinePct >= 0.35;
|
|
204
|
-
return {
|
|
205
|
-
currentLinePrice,
|
|
206
|
-
priceVsLinePctAbs,
|
|
207
|
-
lineTouchedNow,
|
|
208
|
-
failedBounceBreak,
|
|
209
|
-
distance: toFiniteNumberOrNull(line.distance)
|
|
210
|
-
};
|
|
211
|
-
};
|
|
212
|
-
var pickBestCandidateLine = ({
|
|
213
|
-
candle,
|
|
214
|
-
lines
|
|
215
|
-
}) => {
|
|
216
|
-
const ranked = lines.map(({ line, direction }) => {
|
|
217
|
-
const candidateContext = buildReverseTrendlineCandidateContext({
|
|
218
|
-
line,
|
|
219
|
-
candle,
|
|
220
|
-
direction
|
|
221
|
-
});
|
|
222
|
-
return { line, direction, candidateContext };
|
|
223
|
-
}).filter(({ candidateContext }) => candidateContext.currentLinePrice != null).sort((left, right) => {
|
|
224
|
-
const leftTouchRank = left.candidateContext.lineTouchedNow ? 0 : 1;
|
|
225
|
-
const rightTouchRank = right.candidateContext.lineTouchedNow ? 0 : 1;
|
|
226
|
-
if (leftTouchRank !== rightTouchRank) {
|
|
227
|
-
return leftTouchRank - rightTouchRank;
|
|
228
|
-
}
|
|
229
|
-
const leftDistance = left.candidateContext.priceVsLinePctAbs ?? Number.POSITIVE_INFINITY;
|
|
230
|
-
const rightDistance = right.candidateContext.priceVsLinePctAbs ?? Number.POSITIVE_INFINITY;
|
|
231
|
-
if (leftDistance !== rightDistance) {
|
|
232
|
-
return leftDistance - rightDistance;
|
|
233
|
-
}
|
|
234
|
-
return (left.candidateContext.distance ?? Number.POSITIVE_INFINITY) - (right.candidateContext.distance ?? Number.POSITIVE_INFINITY);
|
|
235
|
-
});
|
|
236
|
-
return ranked[0] ?? null;
|
|
237
|
-
};
|
|
238
|
-
var createReverseTrendLineCore = async ({ config: config2, data: cachedData, strategyApi, indicatorsState }) => {
|
|
239
|
-
const { TRENDLINE, FEE_PERCENT, MAX_LOSS_VALUE, HIGHS, LOWS } = config2;
|
|
240
|
-
const lastTradeController = strategyApi.createLastTradeController();
|
|
241
|
-
const trendlineOptions = {
|
|
242
|
-
bestLines: 1,
|
|
243
|
-
capture: true,
|
|
244
|
-
...TRENDLINE
|
|
245
|
-
};
|
|
246
|
-
const getLowsTrendlines = createTrendlineEngine(cachedData, {
|
|
247
|
-
mode: "lows",
|
|
248
|
-
...trendlineOptions
|
|
249
|
-
});
|
|
250
|
-
const getHighsTrendlines = createTrendlineEngine(cachedData, {
|
|
251
|
-
mode: "highs",
|
|
252
|
-
...trendlineOptions
|
|
253
|
-
});
|
|
254
|
-
return async (candle) => {
|
|
255
|
-
const lowsTrendlines = getLowsTrendlines.next(candle);
|
|
256
|
-
const highsTrendlines = getHighsTrendlines.next(candle);
|
|
257
|
-
indicatorsState.onBar();
|
|
258
|
-
const currentPosition = await strategyApi.getCurrentPosition();
|
|
259
|
-
if (isOpenPosition(currentPosition)) {
|
|
260
|
-
const activeLine = currentPosition.direction === "LONG" ? lowsTrendlines[0] : highsTrendlines[0];
|
|
261
|
-
const activeLinePrice = getLinePriceAtNow(
|
|
262
|
-
activeLine ?? null,
|
|
263
|
-
candle.timestamp
|
|
264
|
-
);
|
|
265
|
-
const priceVsLinePct = activeLinePrice != null && activeLinePrice !== 0 ? (candle.close - activeLinePrice) / activeLinePrice * 100 : null;
|
|
266
|
-
const failedBounceBreak = currentPosition.direction === "LONG" ? priceVsLinePct != null && priceVsLinePct <= -0.35 : priceVsLinePct != null && priceVsLinePct >= 0.35;
|
|
267
|
-
if (failedBounceBreak) {
|
|
268
|
-
return strategyApi.exit({
|
|
269
|
-
code: "REVERSE_TRENDLINE_FAILED_BOUNCE_EXIT",
|
|
270
|
-
direction: currentPosition.direction
|
|
271
|
-
});
|
|
272
|
-
}
|
|
273
|
-
return strategyApi.skip("POSITION_EXISTS");
|
|
274
|
-
}
|
|
275
|
-
if (lastTradeController.isInCooldown(candle.timestamp)) {
|
|
276
|
-
return strategyApi.skip("DEV_TRADE_COOLDOWN");
|
|
277
|
-
}
|
|
278
|
-
const candidates = [];
|
|
279
|
-
if (LOWS.enable && lowsTrendlines.length > 0) {
|
|
280
|
-
candidates.push({ line: lowsTrendlines[0], direction: LOWS.direction });
|
|
281
|
-
}
|
|
282
|
-
if (HIGHS.enable && highsTrendlines.length > 0) {
|
|
283
|
-
candidates.push({ line: highsTrendlines[0], direction: HIGHS.direction });
|
|
284
|
-
}
|
|
285
|
-
if (candidates.length === 0) {
|
|
286
|
-
return strategyApi.skip("NO_TRENDLINE");
|
|
287
|
-
}
|
|
288
|
-
const bestCandidate = pickBestCandidateLine({
|
|
289
|
-
candle: {
|
|
290
|
-
timestamp: candle.timestamp,
|
|
291
|
-
open: candle.open,
|
|
292
|
-
close: candle.close,
|
|
293
|
-
high: candle.high,
|
|
294
|
-
low: candle.low
|
|
295
|
-
},
|
|
296
|
-
lines: candidates
|
|
297
|
-
});
|
|
298
|
-
if (!bestCandidate) {
|
|
299
|
-
return strategyApi.skip("NO_TRENDLINE");
|
|
300
|
-
}
|
|
301
|
-
const { line: bestLine, direction, candidateContext } = bestCandidate;
|
|
302
|
-
const modeConfig = direction === "LONG" ? LOWS : HIGHS;
|
|
303
|
-
const { minRiskRatio } = modeConfig;
|
|
304
|
-
if (candidateContext.failedBounceBreak) {
|
|
305
|
-
return strategyApi.skip(
|
|
306
|
-
"REVERSE_TRENDLINE_STRUCTURE:failed_bounce_break"
|
|
307
|
-
);
|
|
308
|
-
}
|
|
309
|
-
const { fullData, timestamp, currentPrice } = await strategyApi.getMarketData();
|
|
310
|
-
if (!filterByVeryVolatility(fullData)) {
|
|
311
|
-
return strategyApi.skip("VERY_VOLATILITY");
|
|
312
|
-
}
|
|
313
|
-
const indicators = indicatorsState.snapshot();
|
|
314
|
-
const signalSeed = buildReverseTrendlineSignalSeed({
|
|
315
|
-
direction,
|
|
316
|
-
currentPrice,
|
|
317
|
-
indicators,
|
|
318
|
-
bestLine,
|
|
319
|
-
currentCandle: {
|
|
320
|
-
timestamp: candle.timestamp,
|
|
321
|
-
open: candle.open,
|
|
322
|
-
close: candle.close,
|
|
323
|
-
high: candle.high,
|
|
324
|
-
low: candle.low
|
|
325
|
-
}
|
|
326
|
-
});
|
|
327
|
-
const structuralContext = buildReverseTrendlineStructuralContext(signalSeed);
|
|
328
|
-
const timingContext = buildReverseTrendlineTimingContext({
|
|
329
|
-
signal: signalSeed,
|
|
330
|
-
candles: fullData,
|
|
331
|
-
structuralContext
|
|
332
|
-
});
|
|
333
|
-
if (!timingContext.entryReadyNow) {
|
|
334
|
-
const timingCode = timingContext.entryTiming === "stale_reaction" ? "STALE_REACTION" : timingContext.entryTiming === "wait_reaction_confirmation" ? "WAIT_REACTION_CONFIRMATION" : "WAIT_TOUCH";
|
|
335
|
-
return strategyApi.skip(`REVERSE_TRENDLINE_TIMING:${timingCode}`);
|
|
336
|
-
}
|
|
337
|
-
const riskPlan = buildReverseTrendlineRiskPlan({
|
|
338
|
-
direction,
|
|
339
|
-
modeConfig,
|
|
340
|
-
structuralContext,
|
|
341
|
-
timingContext
|
|
342
|
-
});
|
|
343
|
-
const { stopLossPrice, takeProfitPrice, riskRatio, qty } = strategyApi.getDirectionalTpSlPrices({
|
|
344
|
-
price: currentPrice,
|
|
345
|
-
direction,
|
|
346
|
-
takeProfitDelta: riskPlan.takeProfitDelta,
|
|
347
|
-
stopLossDelta: riskPlan.stopLossDelta,
|
|
348
|
-
unit: "percent",
|
|
349
|
-
maxLossValue: MAX_LOSS_VALUE,
|
|
350
|
-
feePercent: Number(FEE_PERCENT ?? 0)
|
|
351
|
-
});
|
|
352
|
-
if (!qty || !Number.isFinite(qty) || qty <= 0) {
|
|
353
|
-
return strategyApi.skip("INVALID_QTY");
|
|
354
|
-
}
|
|
355
|
-
if (riskRatio <= minRiskRatio) {
|
|
356
|
-
return strategyApi.skip(`RISK_RATIO:${round2(riskRatio)}`);
|
|
357
|
-
}
|
|
358
|
-
lastTradeController.markTrade(timestamp);
|
|
359
|
-
return strategyApi.entry({
|
|
360
|
-
code: "REVERSE_TRENDLINE_SIGNAL",
|
|
361
|
-
figures: {
|
|
362
|
-
...buildReverseTrendLineFigures(bestLine)
|
|
363
|
-
},
|
|
364
|
-
direction,
|
|
365
|
-
indicators,
|
|
366
|
-
additionalIndicators: buildReverseTrendlineSignalSeed({
|
|
367
|
-
direction,
|
|
368
|
-
currentPrice,
|
|
369
|
-
indicators,
|
|
370
|
-
bestLine,
|
|
371
|
-
currentCandle: {
|
|
372
|
-
timestamp: candle.timestamp,
|
|
373
|
-
open: candle.open,
|
|
374
|
-
close: candle.close,
|
|
375
|
-
high: candle.high,
|
|
376
|
-
low: candle.low
|
|
377
|
-
},
|
|
378
|
-
reverseTrendlineTiming: timingContext
|
|
379
|
-
}).additionalIndicators,
|
|
380
|
-
orderPlan: {
|
|
381
|
-
qty,
|
|
382
|
-
stopLossPrice,
|
|
383
|
-
takeProfits: [{ rate: 1, price: takeProfitPrice }]
|
|
384
|
-
}
|
|
385
|
-
});
|
|
386
|
-
};
|
|
387
|
-
};
|
|
388
|
-
|
|
389
|
-
// src/ReverseTrendLine/strategy.ts
|
|
390
|
-
var ReverseTrendLineStrategyCreator = createStrategyRuntime({
|
|
391
|
-
strategyName: "ReverseTrendLine",
|
|
392
|
-
defaults: config,
|
|
393
|
-
createCore: createReverseTrendLineCore,
|
|
394
|
-
manifest: reverseTrendLineManifest,
|
|
395
|
-
strategyDirectory: __dirname
|
|
396
|
-
});
|
|
397
|
-
export {
|
|
398
|
-
ReverseTrendLineStrategyCreator
|
|
399
|
-
};
|