aiden-shared-calculations-unified 1.0.86 → 1.0.88
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/calculations/capitulation/asset-volatility-estimator.js +96 -0
- package/calculations/capitulation/retail-capitulation-risk-forecast.js +173 -0
- package/calculations/core/asset-cost-basis-profile.js +127 -0
- package/calculations/core/asset-pnl-status.js +36 -106
- package/calculations/core/asset-position-size.js +40 -91
- package/calculations/core/average-daily-pnl-all-users.js +18 -57
- package/calculations/core/average-daily-pnl-per-sector.js +41 -88
- package/calculations/core/average-daily-pnl-per-stock.js +38 -91
- package/calculations/core/average-daily-position-pnl.js +19 -49
- package/calculations/core/holding-duration-per-asset.js +25 -127
- package/calculations/core/instrument-price-change-1d.js +30 -49
- package/calculations/core/instrument-price-momentum-20d.js +50 -60
- package/calculations/core/long-position-per-stock.js +39 -68
- package/calculations/core/overall-holding-duration.js +16 -87
- package/calculations/core/overall-profitability-ratio.js +11 -40
- package/calculations/core/platform-buy-sell-sentiment.js +41 -124
- package/calculations/core/platform-daily-bought-vs-sold-count.js +41 -99
- package/calculations/core/platform-daily-ownership-delta.js +68 -126
- package/calculations/core/platform-ownership-per-sector.js +45 -96
- package/calculations/core/platform-total-positions-held.js +20 -80
- package/calculations/core/pnl-distribution-per-stock.js +29 -135
- package/calculations/core/price-metrics.js +95 -206
- package/calculations/core/profitability-ratio-per-sector.js +34 -79
- package/calculations/core/profitability-ratio-per-stock.js +32 -88
- package/calculations/core/profitability-skew-per-stock.js +41 -94
- package/calculations/core/profitable-and-unprofitable-status.js +44 -76
- package/calculations/core/sentiment-per-stock.js +24 -77
- package/calculations/core/short-position-per-stock.js +35 -43
- package/calculations/core/social-activity-aggregation.js +26 -49
- package/calculations/core/social-asset-posts-trend.js +38 -94
- package/calculations/core/social-event-correlation.js +26 -93
- package/calculations/core/social-sentiment-aggregation.js +20 -44
- package/calculations/core/social-top-mentioned-words.js +35 -87
- package/calculations/core/social-topic-interest-evolution.js +22 -111
- package/calculations/core/social-topic-sentiment-matrix.js +38 -104
- package/calculations/core/social-word-mentions-trend.js +27 -104
- package/calculations/core/speculator-asset-sentiment.js +31 -72
- package/calculations/core/speculator-danger-zone.js +48 -84
- package/calculations/core/speculator-distance-to-stop-loss-per-leverage.js +20 -52
- package/calculations/core/speculator-distance-to-tp-per-leverage.js +23 -53
- package/calculations/core/speculator-entry-distance-to-sl-per-leverage.js +20 -50
- package/calculations/core/speculator-entry-distance-to-tp-per-leverage.js +23 -50
- package/calculations/core/speculator-leverage-per-asset.js +25 -64
- package/calculations/core/speculator-leverage-per-sector.js +27 -63
- package/calculations/core/speculator-risk-reward-ratio-per-asset.js +24 -53
- package/calculations/core/speculator-stop-loss-distance-by-sector-short-long-breakdown.js +55 -68
- package/calculations/core/speculator-stop-loss-distance-by-ticker-short-long-breakdown.js +54 -71
- package/calculations/core/speculator-stop-loss-per-asset.js +19 -44
- package/calculations/core/speculator-take-profit-per-asset.js +20 -57
- package/calculations/core/speculator-tsl-per-asset.js +17 -56
- package/calculations/core/test..js +0 -0
- package/calculations/core/total-long-figures.js +16 -31
- package/calculations/core/total-long-per-sector.js +39 -61
- package/calculations/core/total-short-figures.js +13 -32
- package/calculations/core/total-short-per-sector.js +39 -61
- package/calculations/core/users-processed.js +11 -46
- package/calculations/gauss/cohort-capital-flow.js +54 -173
- package/calculations/gauss/cohort-definer.js +77 -163
- package/calculations/gauss/daily-dna-filter.js +29 -83
- package/calculations/gauss/gauss-divergence-signal.js +22 -109
- package/calculations/gem/cohort-momentum-state.js +27 -72
- package/calculations/gem/cohort-skill-definition.js +36 -52
- package/calculations/gem/platform-conviction-divergence.js +18 -60
- package/calculations/gem/quant-skill-alpha-signal.js +25 -98
- package/calculations/gem/skilled-cohort-flow.js +67 -175
- package/calculations/gem/skilled-unskilled-divergence.js +18 -73
- package/calculations/gem/unskilled-cohort-flow.js +64 -172
- package/calculations/ghost-book/cost-basis-density.js +79 -0
- package/calculations/ghost-book/liquidity-vacuum.js +52 -0
- package/calculations/ghost-book/retail-gamma-exposure.js +86 -0
- package/calculations/helix/helix-contrarian-signal.js +20 -114
- package/calculations/helix/herd-consensus-score.js +42 -124
- package/calculations/helix/winner-loser-flow.js +36 -118
- package/calculations/predicative-alpha/cognitive-dissonance.js +113 -0
- package/calculations/predicative-alpha/diamond-hand-fracture.js +90 -0
- package/calculations/predicative-alpha/mimetic-latency.js +124 -0
- package/calculations/pyro/risk-appetite-index.js +33 -74
- package/calculations/pyro/squeeze-potential.js +30 -87
- package/calculations/pyro/volatility-signal.js +33 -78
- package/package.json +1 -1
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview Calculation (Pass 1) for speculator
|
|
3
|
-
*
|
|
4
|
-
* - Rewritten logic to calculate *entry* SL distance from raw schema fields
|
|
5
|
-
* (StopLossRate, OpenRate) instead of the non-existent
|
|
6
|
-
* 'PctToStopLossAtEntry' field.
|
|
7
|
-
* - Updated process signature to match worker.
|
|
2
|
+
* @fileoverview Calculation (Pass 1) for speculator Entry distance to SL.
|
|
3
|
+
* REFACTORED: Uses extract.getOpenRate vs extract.getStopLossRate.
|
|
8
4
|
*/
|
|
9
|
-
const BUCKETS = [1, 2, 5, 10, 20, 30];
|
|
5
|
+
const BUCKETS = [1, 2, 5, 10, 20, 30];
|
|
10
6
|
|
|
11
7
|
class SpeculatorEntryDistanceToSLPerLeverage {
|
|
12
8
|
constructor() {
|
|
@@ -16,9 +12,7 @@ class SpeculatorEntryDistanceToSLPerLeverage {
|
|
|
16
12
|
|
|
17
13
|
_initBuckets() {
|
|
18
14
|
this.buckets.clear();
|
|
19
|
-
for (const b of BUCKETS) {
|
|
20
|
-
this.buckets.set(b, { sum: 0, count: 0 });
|
|
21
|
-
}
|
|
15
|
+
for (const b of BUCKETS) this.buckets.set(b, { sum: 0, count: 0 });
|
|
22
16
|
this.buckets.set('other', { sum: 0, count: 0 });
|
|
23
17
|
}
|
|
24
18
|
|
|
@@ -32,9 +26,7 @@ class SpeculatorEntryDistanceToSLPerLeverage {
|
|
|
32
26
|
};
|
|
33
27
|
}
|
|
34
28
|
|
|
35
|
-
static getDependencies() {
|
|
36
|
-
return [];
|
|
37
|
-
}
|
|
29
|
+
static getDependencies() { return []; }
|
|
38
30
|
|
|
39
31
|
static getSchema() {
|
|
40
32
|
const bucketSchema = {
|
|
@@ -44,47 +36,29 @@ class SpeculatorEntryDistanceToSLPerLeverage {
|
|
|
44
36
|
"position_count": { "type": "number" }
|
|
45
37
|
}
|
|
46
38
|
};
|
|
47
|
-
|
|
48
|
-
return {
|
|
49
|
-
"type": "object",
|
|
50
|
-
"description": "Calculates the average *entry* distance to stop-loss, bucketed by leverage.",
|
|
51
|
-
"properties": {
|
|
52
|
-
"x1": bucketSchema,
|
|
53
|
-
"x2": bucketSchema,
|
|
54
|
-
"x5": bucketSchema,
|
|
55
|
-
"x10": bucketSchema,
|
|
56
|
-
"x20": bucketSchema,
|
|
57
|
-
"x30": bucketSchema,
|
|
58
|
-
"other": bucketSchema
|
|
59
|
-
}
|
|
60
|
-
};
|
|
39
|
+
return { "type": "object", "patternProperties": { "^.*$": bucketSchema } };
|
|
61
40
|
}
|
|
62
41
|
|
|
63
42
|
_getBucket(leverage) {
|
|
64
|
-
|
|
65
|
-
return this.buckets.get(leverage);
|
|
66
|
-
}
|
|
67
|
-
return this.buckets.get('other');
|
|
43
|
+
return this.buckets.has(leverage) ? this.buckets.get(leverage) : this.buckets.get('other');
|
|
68
44
|
}
|
|
69
45
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
46
|
+
process(context) {
|
|
47
|
+
const { extract } = context.math;
|
|
48
|
+
const { user } = context;
|
|
49
|
+
const positions = extract.getPositions(user.portfolio.today, user.type);
|
|
76
50
|
|
|
77
51
|
for (const pos of positions) {
|
|
78
|
-
const leverage = pos
|
|
79
|
-
const slRate = pos
|
|
80
|
-
const openRate = pos
|
|
52
|
+
const leverage = extract.getLeverage(pos);
|
|
53
|
+
const slRate = extract.getStopLossRate(pos);
|
|
54
|
+
const openRate = extract.getOpenRate(pos);
|
|
81
55
|
|
|
82
|
-
if (!leverage || !slRate || slRate <= 0 || !openRate || openRate <= 0)
|
|
83
|
-
continue;
|
|
84
|
-
}
|
|
56
|
+
if (!leverage || !slRate || slRate <= 0 || !openRate || openRate <= 0) continue;
|
|
85
57
|
|
|
58
|
+
const direction = extract.getDirection(pos);
|
|
86
59
|
let pctToSL = 0;
|
|
87
|
-
|
|
60
|
+
|
|
61
|
+
if (direction === 'Buy') {
|
|
88
62
|
// Long: (Open - SL) / Open
|
|
89
63
|
pctToSL = (openRate - slRate) / openRate;
|
|
90
64
|
} else {
|
|
@@ -92,16 +66,13 @@ class SpeculatorEntryDistanceToSLPerLeverage {
|
|
|
92
66
|
pctToSL = (slRate - openRate) / openRate;
|
|
93
67
|
}
|
|
94
68
|
|
|
95
|
-
if (pctToSL <= 0)
|
|
96
|
-
continue; // SL is at or beyond open price, invalid
|
|
97
|
-
}
|
|
69
|
+
if (pctToSL <= 0) continue; // Invalid distance
|
|
98
70
|
|
|
99
71
|
const bucket = this._getBucket(leverage);
|
|
100
|
-
bucket.sum += (pctToSL * 100);
|
|
72
|
+
bucket.sum += (pctToSL * 100);
|
|
101
73
|
bucket.count++;
|
|
102
74
|
}
|
|
103
75
|
}
|
|
104
|
-
// --- END FIX ---
|
|
105
76
|
|
|
106
77
|
getResult() {
|
|
107
78
|
const result = {};
|
|
@@ -119,5 +90,4 @@ class SpeculatorEntryDistanceToSLPerLeverage {
|
|
|
119
90
|
this._initBuckets();
|
|
120
91
|
}
|
|
121
92
|
}
|
|
122
|
-
|
|
123
93
|
module.exports = SpeculatorEntryDistanceToSLPerLeverage;
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview Calculation (Pass 1) for speculator TP
|
|
3
|
-
*
|
|
4
|
-
* - Rewritten logic to calculate *entry* TP distance from raw schema fields
|
|
5
|
-
* (TakeProfitRate, OpenRate) instead of the non-existent
|
|
6
|
-
* 'PctToTakeProfitAtEntry' field.
|
|
7
|
-
* - Updated process signature to match worker.
|
|
2
|
+
* @fileoverview Calculation (Pass 1) for speculator TP Entry distance (Open Price vs TP).
|
|
3
|
+
* REFACTORED: Uses context.math.extract.
|
|
8
4
|
*/
|
|
9
|
-
const BUCKETS = [1, 2, 5, 10, 20, 30];
|
|
5
|
+
const BUCKETS = [1, 2, 5, 10, 20, 30];
|
|
10
6
|
|
|
11
|
-
class
|
|
7
|
+
class SpeculatorEntryDistanceToTpPerLeverage {
|
|
12
8
|
constructor() {
|
|
13
9
|
this.buckets = new Map();
|
|
14
10
|
this._initBuckets();
|
|
@@ -16,9 +12,7 @@ class SpeculatorEntryDistanceToTPPerLeverage {
|
|
|
16
12
|
|
|
17
13
|
_initBuckets() {
|
|
18
14
|
this.buckets.clear();
|
|
19
|
-
for (const b of BUCKETS) {
|
|
20
|
-
this.buckets.set(b, { sum: 0, count: 0 });
|
|
21
|
-
}
|
|
15
|
+
for (const b of BUCKETS) this.buckets.set(b, { sum: 0, count: 0 });
|
|
22
16
|
this.buckets.set('other', { sum: 0, count: 0 });
|
|
23
17
|
}
|
|
24
18
|
|
|
@@ -27,14 +21,12 @@ class SpeculatorEntryDistanceToTPPerLeverage {
|
|
|
27
21
|
type: 'standard',
|
|
28
22
|
rootDataDependencies: ['portfolio'],
|
|
29
23
|
isHistorical: false,
|
|
30
|
-
userType: 'speculator',
|
|
24
|
+
userType: 'speculator',
|
|
31
25
|
category: 'core_speculator'
|
|
32
26
|
};
|
|
33
27
|
}
|
|
34
28
|
|
|
35
|
-
static getDependencies() {
|
|
36
|
-
return [];
|
|
37
|
-
}
|
|
29
|
+
static getDependencies() { return []; }
|
|
38
30
|
|
|
39
31
|
static getSchema() {
|
|
40
32
|
const bucketSchema = {
|
|
@@ -44,47 +36,32 @@ class SpeculatorEntryDistanceToTPPerLeverage {
|
|
|
44
36
|
"position_count": { "type": "number" }
|
|
45
37
|
}
|
|
46
38
|
};
|
|
47
|
-
|
|
48
|
-
return {
|
|
49
|
-
"type": "object",
|
|
50
|
-
"description": "Calculates the average *entry* distance to take-profit, bucketed by leverage.",
|
|
51
|
-
"properties": {
|
|
52
|
-
"x1": bucketSchema,
|
|
53
|
-
"x2": bucketSchema,
|
|
54
|
-
"x5": bucketSchema,
|
|
55
|
-
"x10": bucketSchema,
|
|
56
|
-
"x20": bucketSchema,
|
|
57
|
-
"x30": bucketSchema,
|
|
58
|
-
"other": bucketSchema
|
|
59
|
-
}
|
|
60
|
-
};
|
|
39
|
+
return { "type": "object", "patternProperties": { "^.*$": bucketSchema } };
|
|
61
40
|
}
|
|
62
41
|
|
|
63
42
|
_getBucket(leverage) {
|
|
64
|
-
|
|
65
|
-
return this.buckets.get(leverage);
|
|
66
|
-
}
|
|
67
|
-
return this.buckets.get('other');
|
|
43
|
+
return this.buckets.has(leverage) ? this.buckets.get(leverage) : this.buckets.get('other');
|
|
68
44
|
}
|
|
69
45
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
46
|
+
process(context) {
|
|
47
|
+
const { extract } = context.math;
|
|
48
|
+
const { user } = context;
|
|
49
|
+
|
|
50
|
+
const positions = extract.getPositions(user.portfolio.today, user.type);
|
|
76
51
|
|
|
77
52
|
for (const pos of positions) {
|
|
78
|
-
const leverage = pos
|
|
79
|
-
const tpRate = pos
|
|
80
|
-
const openRate = pos
|
|
53
|
+
const leverage = extract.getLeverage(pos);
|
|
54
|
+
const tpRate = extract.getTakeProfitRate(pos);
|
|
55
|
+
const openRate = extract.getOpenRate(pos);
|
|
81
56
|
|
|
82
57
|
if (!leverage || !tpRate || tpRate <= 0 || !openRate || openRate <= 0) {
|
|
83
58
|
continue;
|
|
84
59
|
}
|
|
85
60
|
|
|
61
|
+
const direction = extract.getDirection(pos);
|
|
86
62
|
let pctToTP = 0;
|
|
87
|
-
|
|
63
|
+
|
|
64
|
+
if (direction === 'Buy') {
|
|
88
65
|
// Long: (TP - Open) / Open
|
|
89
66
|
pctToTP = (tpRate - openRate) / openRate;
|
|
90
67
|
} else {
|
|
@@ -92,16 +69,13 @@ class SpeculatorEntryDistanceToTPPerLeverage {
|
|
|
92
69
|
pctToTP = (openRate - tpRate) / openRate;
|
|
93
70
|
}
|
|
94
71
|
|
|
95
|
-
if (pctToTP <= 0)
|
|
96
|
-
continue; // TP is at or below open price, invalid
|
|
97
|
-
}
|
|
72
|
+
if (pctToTP <= 0) continue;
|
|
98
73
|
|
|
99
74
|
const bucket = this._getBucket(leverage);
|
|
100
|
-
bucket.sum += (pctToTP * 100);
|
|
75
|
+
bucket.sum += (pctToTP * 100);
|
|
101
76
|
bucket.count++;
|
|
102
77
|
}
|
|
103
78
|
}
|
|
104
|
-
// --- END FIX ---
|
|
105
79
|
|
|
106
80
|
getResult() {
|
|
107
81
|
const result = {};
|
|
@@ -119,5 +93,4 @@ class SpeculatorEntryDistanceToTPPerLeverage {
|
|
|
119
93
|
this._initBuckets();
|
|
120
94
|
}
|
|
121
95
|
}
|
|
122
|
-
|
|
123
|
-
module.exports = SpeculatorEntryDistanceToTPPerLeverage;
|
|
96
|
+
module.exports = SpeculatorEntryDistanceToTpPerLeverage;
|
|
@@ -1,42 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview Calculation (Pass 1) for speculator leverage.
|
|
3
|
-
*
|
|
4
|
-
* This metric answers: "For each asset, what is the average
|
|
5
|
-
* leverage used by speculators?"
|
|
2
|
+
* @fileoverview Calculation (Pass 1) for speculator leverage per asset.
|
|
3
|
+
* REFACTORED: Uses context.math.extract.getLeverage.
|
|
6
4
|
*/
|
|
7
|
-
// --- STANDARD 0: REMOVED require('../../utils/sector_mapping_provider') ---
|
|
8
|
-
|
|
9
5
|
class SpeculatorLeveragePerAsset {
|
|
10
6
|
constructor() {
|
|
11
|
-
// { [instrumentId]: { sum: 0, count: 0 } }
|
|
12
7
|
this.assets = new Map();
|
|
13
|
-
// --- STANDARD 0: RENAMED ---
|
|
14
8
|
this.tickerMap = null;
|
|
15
9
|
}
|
|
16
10
|
|
|
17
|
-
/**
|
|
18
|
-
* Statically defines all metadata for the manifest builder.
|
|
19
|
-
*/
|
|
20
11
|
static getMetadata() {
|
|
21
12
|
return {
|
|
22
13
|
type: 'standard',
|
|
23
14
|
rootDataDependencies: ['portfolio'],
|
|
24
15
|
isHistorical: false,
|
|
25
|
-
userType: 'speculator',
|
|
16
|
+
userType: 'speculator',
|
|
26
17
|
category: 'core_speculator'
|
|
27
18
|
};
|
|
28
19
|
}
|
|
29
20
|
|
|
30
|
-
|
|
31
|
-
* Statically declare dependencies.
|
|
32
|
-
*/
|
|
33
|
-
static getDependencies() {
|
|
34
|
-
return [];
|
|
35
|
-
}
|
|
21
|
+
static getDependencies() { return []; }
|
|
36
22
|
|
|
37
|
-
/**
|
|
38
|
-
* Defines the output schema for this calculation.
|
|
39
|
-
*/
|
|
40
23
|
static getSchema() {
|
|
41
24
|
const tickerSchema = {
|
|
42
25
|
"type": "object",
|
|
@@ -46,64 +29,44 @@ class SpeculatorLeveragePerAsset {
|
|
|
46
29
|
},
|
|
47
30
|
"required": ["avg_leverage", "position_count"]
|
|
48
31
|
};
|
|
49
|
-
|
|
50
|
-
return {
|
|
51
|
-
"type": "object",
|
|
52
|
-
"description": "Calculates the average leverage used by speculators for each asset.",
|
|
53
|
-
"patternProperties": { "^.*$": tickerSchema },
|
|
54
|
-
"additionalProperties": tickerSchema
|
|
55
|
-
};
|
|
32
|
+
return { "type": "object", "patternProperties": { "^.*$": tickerSchema } };
|
|
56
33
|
}
|
|
57
34
|
|
|
58
35
|
_initAsset(instrumentId) {
|
|
59
36
|
if (!this.assets.has(instrumentId)) {
|
|
60
|
-
this.assets.set(instrumentId, {
|
|
37
|
+
this.assets.set(instrumentId, { leverageSum: 0, count: 0 });
|
|
61
38
|
}
|
|
62
39
|
}
|
|
63
40
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
if (!this.tickerMap)
|
|
68
|
-
this.tickerMap = context.instrumentToTicker;
|
|
69
|
-
}
|
|
41
|
+
process(context) {
|
|
42
|
+
const { extract } = context.math;
|
|
43
|
+
const { mappings, user } = context;
|
|
44
|
+
if (!this.tickerMap) this.tickerMap = mappings.instrumentToTicker;
|
|
70
45
|
|
|
71
|
-
const positions =
|
|
72
|
-
if (!positions || !Array.isArray(positions)) {
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
46
|
+
const positions = extract.getPositions(user.portfolio.today, user.type);
|
|
75
47
|
|
|
76
48
|
for (const pos of positions) {
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
if (!instrumentId || !leverage || leverage <= 1) {
|
|
81
|
-
continue; // Only care about leveraged positions
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
this._initAsset(instrumentId);
|
|
85
|
-
const assetData = this.assets.get(instrumentId);
|
|
86
|
-
assetData.sum += leverage;
|
|
87
|
-
assetData.count++;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
49
|
+
const instId = extract.getInstrumentId(pos);
|
|
50
|
+
if (!instId) continue;
|
|
90
51
|
|
|
91
|
-
|
|
92
|
-
|
|
52
|
+
const leverage = extract.getLeverage(pos);
|
|
53
|
+
if (leverage <= 0) continue;
|
|
93
54
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
55
|
+
this._initAsset(instId);
|
|
56
|
+
const data = this.assets.get(instId);
|
|
57
|
+
data.leverageSum += leverage;
|
|
58
|
+
data.count++;
|
|
97
59
|
}
|
|
60
|
+
}
|
|
98
61
|
|
|
62
|
+
async getResult() {
|
|
63
|
+
if (!this.tickerMap) return {};
|
|
99
64
|
const result = {};
|
|
100
|
-
for (const [
|
|
101
|
-
|
|
102
|
-
const ticker = this.tickerMap[instrumentId] || `id_${instrumentId}`;
|
|
103
|
-
|
|
65
|
+
for (const [instId, data] of this.assets.entries()) {
|
|
66
|
+
const ticker = this.tickerMap[instId] || `id_${instId}`;
|
|
104
67
|
if (data.count > 0) {
|
|
105
68
|
result[ticker] = {
|
|
106
|
-
avg_leverage: data.
|
|
69
|
+
avg_leverage: data.leverageSum / data.count,
|
|
107
70
|
position_count: data.count
|
|
108
71
|
};
|
|
109
72
|
}
|
|
@@ -113,9 +76,7 @@ class SpeculatorLeveragePerAsset {
|
|
|
113
76
|
|
|
114
77
|
reset() {
|
|
115
78
|
this.assets.clear();
|
|
116
|
-
// --- STANDARD 0: RENAMED ---
|
|
117
79
|
this.tickerMap = null;
|
|
118
80
|
}
|
|
119
81
|
}
|
|
120
|
-
|
|
121
82
|
module.exports = SpeculatorLeveragePerAsset;
|
|
@@ -1,42 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview Calculation (Pass 1) for speculator leverage.
|
|
3
|
-
*
|
|
4
|
-
* This metric answers: "For each sector, what is the average
|
|
5
|
-
* leverage used by speculators?"
|
|
2
|
+
* @fileoverview Calculation (Pass 1) for speculator leverage per sector.
|
|
3
|
+
* REFACTORED: Uses context.math.extract.
|
|
6
4
|
*/
|
|
7
|
-
// --- STANDARD 0: REMOVED require('../../utils/sector_mapping_provider') ---
|
|
8
|
-
|
|
9
5
|
class SpeculatorLeveragePerSector {
|
|
10
6
|
constructor() {
|
|
11
|
-
|
|
12
|
-
this.sectors = new Map();
|
|
13
|
-
// --- STANDARD 0: RENAMED ---
|
|
7
|
+
this.sectorData = new Map();
|
|
14
8
|
this.sectorMap = null;
|
|
15
9
|
}
|
|
16
10
|
|
|
17
|
-
/**
|
|
18
|
-
* Statically defines all metadata for the manifest builder.
|
|
19
|
-
*/
|
|
20
11
|
static getMetadata() {
|
|
21
12
|
return {
|
|
22
13
|
type: 'standard',
|
|
23
14
|
rootDataDependencies: ['portfolio'],
|
|
24
15
|
isHistorical: false,
|
|
25
|
-
userType: 'speculator',
|
|
16
|
+
userType: 'speculator',
|
|
26
17
|
category: 'core_speculator'
|
|
27
18
|
};
|
|
28
19
|
}
|
|
29
20
|
|
|
30
|
-
|
|
31
|
-
* Statically declare dependencies.
|
|
32
|
-
*/
|
|
33
|
-
static getDependencies() {
|
|
34
|
-
return [];
|
|
35
|
-
}
|
|
21
|
+
static getDependencies() { return []; }
|
|
36
22
|
|
|
37
|
-
/**
|
|
38
|
-
* Defines the output schema for this calculation.
|
|
39
|
-
*/
|
|
40
23
|
static getSchema() {
|
|
41
24
|
const sectorSchema = {
|
|
42
25
|
"type": "object",
|
|
@@ -46,59 +29,42 @@ class SpeculatorLeveragePerSector {
|
|
|
46
29
|
},
|
|
47
30
|
"required": ["avg_leverage", "position_count"]
|
|
48
31
|
};
|
|
49
|
-
|
|
50
|
-
return {
|
|
51
|
-
"type": "object",
|
|
52
|
-
"description": "Calculates the average leverage used by speculators for each sector.",
|
|
53
|
-
"patternProperties": { "^.*$": sectorSchema },
|
|
54
|
-
"additionalProperties": sectorSchema
|
|
55
|
-
};
|
|
32
|
+
return { "type": "object", "patternProperties": { "^.*$": sectorSchema } };
|
|
56
33
|
}
|
|
57
34
|
|
|
58
|
-
_initSector(
|
|
59
|
-
if (!this.
|
|
60
|
-
this.
|
|
35
|
+
_initSector(sector) {
|
|
36
|
+
if (!this.sectorData.has(sector)) {
|
|
37
|
+
this.sectorData.set(sector, { leverageSum: 0, count: 0 });
|
|
61
38
|
}
|
|
62
39
|
}
|
|
63
40
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
if (!this.sectorMap)
|
|
68
|
-
this.sectorMap = context.sectorMapping;
|
|
69
|
-
}
|
|
41
|
+
process(context) {
|
|
42
|
+
const { extract } = context.math;
|
|
43
|
+
const { mappings, user } = context;
|
|
44
|
+
if (!this.sectorMap) this.sectorMap = mappings.sectorMapping;
|
|
70
45
|
|
|
71
|
-
const positions =
|
|
72
|
-
if (!positions || !Array.isArray(positions) || !this.sectorMap) {
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
46
|
+
const positions = extract.getPositions(user.portfolio.today, user.type);
|
|
75
47
|
|
|
76
48
|
for (const pos of positions) {
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// --- STANDARD 0: FIXED ---
|
|
85
|
-
const sectorName = this.sectorMap[instrumentId] || 'N/A';
|
|
86
|
-
this._initSector(sectorName);
|
|
87
|
-
const sectorData = this.sectors.get(sectorName);
|
|
49
|
+
const instId = extract.getInstrumentId(pos);
|
|
50
|
+
if (!instId) continue;
|
|
51
|
+
|
|
52
|
+
const sector = this.sectorMap[instId] || 'Unknown';
|
|
53
|
+
const leverage = extract.getLeverage(pos);
|
|
88
54
|
|
|
89
|
-
|
|
90
|
-
sectorData.
|
|
55
|
+
this._initSector(sector);
|
|
56
|
+
const data = this.sectorData.get(sector);
|
|
57
|
+
data.leverageSum += leverage;
|
|
58
|
+
data.count++;
|
|
91
59
|
}
|
|
92
60
|
}
|
|
93
61
|
|
|
94
62
|
async getResult() {
|
|
95
|
-
// --- STANDARD 0: REMOVED forbidden data load ---
|
|
96
|
-
|
|
97
63
|
const result = {};
|
|
98
|
-
for (const [
|
|
64
|
+
for (const [sector, data] of this.sectorData.entries()) {
|
|
99
65
|
if (data.count > 0) {
|
|
100
|
-
result[
|
|
101
|
-
avg_leverage: data.
|
|
66
|
+
result[sector] = {
|
|
67
|
+
avg_leverage: data.leverageSum / data.count,
|
|
102
68
|
position_count: data.count
|
|
103
69
|
};
|
|
104
70
|
}
|
|
@@ -107,10 +73,8 @@ class SpeculatorLeveragePerSector {
|
|
|
107
73
|
}
|
|
108
74
|
|
|
109
75
|
reset() {
|
|
110
|
-
this.
|
|
111
|
-
// --- STANDARD 0: RENAMED ---
|
|
76
|
+
this.sectorData.clear();
|
|
112
77
|
this.sectorMap = null;
|
|
113
78
|
}
|
|
114
79
|
}
|
|
115
|
-
|
|
116
80
|
module.exports = SpeculatorLeveragePerSector;
|
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileoverview Calculation (Pass 1) for speculator R/R.
|
|
3
|
-
*
|
|
4
|
-
* - Rewritten logic to calculate R/R from raw schema fields
|
|
5
|
-
* (OpenRate, StopLossRate, TakeProfitRate) instead of non-existent
|
|
6
|
-
* 'PctTo...' fields.
|
|
7
|
-
* - Updated process signature to match worker.
|
|
3
|
+
* REFACTORED: Uses rate extraction.
|
|
8
4
|
*/
|
|
9
|
-
|
|
10
5
|
class SpeculatorRiskRewardRatioPerAsset {
|
|
11
6
|
constructor() {
|
|
12
7
|
this.assets = new Map();
|
|
@@ -18,14 +13,12 @@ class SpeculatorRiskRewardRatioPerAsset {
|
|
|
18
13
|
type: 'standard',
|
|
19
14
|
rootDataDependencies: ['portfolio'],
|
|
20
15
|
isHistorical: false,
|
|
21
|
-
userType: 'speculator',
|
|
16
|
+
userType: 'speculator',
|
|
22
17
|
category: 'core_speculator'
|
|
23
18
|
};
|
|
24
19
|
}
|
|
25
20
|
|
|
26
|
-
static getDependencies() {
|
|
27
|
-
return [];
|
|
28
|
-
}
|
|
21
|
+
static getDependencies() { return []; }
|
|
29
22
|
|
|
30
23
|
static getSchema() {
|
|
31
24
|
const tickerSchema = {
|
|
@@ -36,13 +29,7 @@ class SpeculatorRiskRewardRatioPerAsset {
|
|
|
36
29
|
},
|
|
37
30
|
"required": ["avg_rr_ratio", "position_count"]
|
|
38
31
|
};
|
|
39
|
-
|
|
40
|
-
return {
|
|
41
|
-
"type": "object",
|
|
42
|
-
"description": "Calculates the average Risk/Reward ratio at entry for speculators per asset.",
|
|
43
|
-
"patternProperties": { "^.*$": tickerSchema },
|
|
44
|
-
"additionalProperties": tickerSchema
|
|
45
|
-
};
|
|
32
|
+
return { "type": "object", "patternProperties": { "^.*$": tickerSchema } };
|
|
46
33
|
}
|
|
47
34
|
|
|
48
35
|
_initAsset(instrumentId) {
|
|
@@ -51,65 +38,50 @@ class SpeculatorRiskRewardRatioPerAsset {
|
|
|
51
38
|
}
|
|
52
39
|
}
|
|
53
40
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
41
|
+
process(context) {
|
|
42
|
+
const { extract } = context.math;
|
|
43
|
+
const { mappings, user } = context;
|
|
44
|
+
if (!this.tickerMap) this.tickerMap = mappings.instrumentToTicker;
|
|
59
45
|
|
|
60
|
-
const positions =
|
|
61
|
-
if (!positions || !Array.isArray(positions)) {
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
46
|
+
const positions = extract.getPositions(user.portfolio.today, user.type);
|
|
64
47
|
|
|
65
48
|
for (const pos of positions) {
|
|
66
|
-
const
|
|
67
|
-
const slRate = pos
|
|
68
|
-
const tpRate = pos
|
|
69
|
-
const openRate = pos
|
|
49
|
+
const instId = extract.getInstrumentId(pos);
|
|
50
|
+
const slRate = extract.getStopLossRate(pos);
|
|
51
|
+
const tpRate = extract.getTakeProfitRate(pos);
|
|
52
|
+
const openRate = extract.getOpenRate(pos);
|
|
70
53
|
|
|
71
|
-
if (!
|
|
72
|
-
continue;
|
|
54
|
+
if (!instId || !slRate || slRate <= 0 || !tpRate || tpRate <= 0 || !openRate || openRate <= 0) {
|
|
55
|
+
continue;
|
|
73
56
|
}
|
|
74
57
|
|
|
58
|
+
const direction = extract.getDirection(pos);
|
|
75
59
|
let risk = 0;
|
|
76
60
|
let reward = 0;
|
|
77
61
|
|
|
78
|
-
if (
|
|
79
|
-
// Long
|
|
62
|
+
if (direction === 'Buy') {
|
|
80
63
|
risk = openRate - slRate;
|
|
81
64
|
reward = tpRate - openRate;
|
|
82
65
|
} else {
|
|
83
|
-
// Short
|
|
84
66
|
risk = slRate - openRate;
|
|
85
67
|
reward = openRate - tpRate;
|
|
86
68
|
}
|
|
87
69
|
|
|
88
|
-
|
|
89
|
-
if (risk <= 0 || reward <= 0) {
|
|
90
|
-
continue;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
this._initAsset(instrumentId);
|
|
94
|
-
const assetData = this.assets.get(instrumentId);
|
|
70
|
+
if (risk <= 0 || reward <= 0) continue;
|
|
95
71
|
|
|
96
|
-
|
|
72
|
+
this._initAsset(instId);
|
|
73
|
+
const assetData = this.assets.get(instId);
|
|
97
74
|
|
|
98
|
-
assetData.sum +=
|
|
75
|
+
assetData.sum += (reward / risk);
|
|
99
76
|
assetData.count++;
|
|
100
77
|
}
|
|
101
78
|
}
|
|
102
|
-
// --- END FIX ---
|
|
103
79
|
|
|
104
80
|
async getResult() {
|
|
105
|
-
if (!this.tickerMap) {
|
|
106
|
-
return {};
|
|
107
|
-
}
|
|
108
|
-
|
|
81
|
+
if (!this.tickerMap) return {};
|
|
109
82
|
const result = {};
|
|
110
|
-
for (const [
|
|
111
|
-
const ticker = this.tickerMap[
|
|
112
|
-
|
|
83
|
+
for (const [instId, data] of this.assets.entries()) {
|
|
84
|
+
const ticker = this.tickerMap[instId] || `id_${instId}`;
|
|
113
85
|
if (data.count > 0) {
|
|
114
86
|
result[ticker] = {
|
|
115
87
|
avg_rr_ratio: data.sum / data.count,
|
|
@@ -125,5 +97,4 @@ class SpeculatorRiskRewardRatioPerAsset {
|
|
|
125
97
|
this.tickerMap = null;
|
|
126
98
|
}
|
|
127
99
|
}
|
|
128
|
-
|
|
129
100
|
module.exports = SpeculatorRiskRewardRatioPerAsset;
|