create-polymarket-strategy 0.2.0 → 0.2.1

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.
@@ -4,8 +4,9 @@
4
4
  * Orchestrates the scanning process:
5
5
  * 1. Calls strategy.scan() to find signals
6
6
  * 2. Checks for duplicate pending orders
7
- * 3. Calculates prices using strategy.calculatePrice()
8
- * 4. Places orders via OrderManager (routes to Lambda for live mode)
7
+ * 3. Checks risk limits before placing
8
+ * 4. Calculates prices using strategy.calculatePrice()
9
+ * 5. Places orders via OrderManager (routes to Lambda for live mode)
9
10
  */
10
11
 
11
12
  import type { Env } from "./types.js";
@@ -14,13 +15,17 @@ import {
14
15
  type StrategyContext,
15
16
  type Order,
16
17
  type NewOrder,
18
+ type TokenInventory,
19
+ type RiskLimits,
17
20
  MarketDataClient,
18
21
  createOrderManagerFromEnv,
22
+ checkOrderRisk,
19
23
  } from "polymarket-trading-sdk";
20
24
 
21
25
  export interface ScanResult {
22
26
  signalsFound: number;
23
27
  ordersPlaced: number;
28
+ ordersSkippedRisk: number;
24
29
  errors: string[];
25
30
  }
26
31
 
@@ -34,6 +39,7 @@ export async function runScanner(
34
39
  const result: ScanResult = {
35
40
  signalsFound: 0,
36
41
  ordersPlaced: 0,
42
+ ordersSkippedRisk: 0,
37
43
  errors: [],
38
44
  };
39
45
 
@@ -60,6 +66,9 @@ export async function runScanner(
60
66
  const ordersId = env.ORDERS.idFromName("main");
61
67
  const ordersStub = env.ORDERS.get(ordersId);
62
68
 
69
+ const positionsId = env.POSITIONS.idFromName("main");
70
+ const positionsStub = env.POSITIONS.get(positionsId);
71
+
63
72
  try {
64
73
  // 1. Scan for signals
65
74
  const signals = await strategy.scan(ctx);
@@ -75,7 +84,24 @@ export async function runScanner(
75
84
  );
76
85
  const pendingOrders = (await pendingOrdersResponse.json()) as Order[];
77
86
 
78
- // 3. Process each signal
87
+ // 3. Get current inventories for risk checking
88
+ const inventoryResponse = await positionsStub.fetch(
89
+ new Request("http://do/inventory/all")
90
+ );
91
+ const inventories = (await inventoryResponse.json()) as TokenInventory[];
92
+
93
+ // 4. Get risk limits from config (with defaults)
94
+ const riskLimits: RiskLimits = {
95
+ maxPositionPerToken: (config.maxPositionPerToken as number) ?? 100,
96
+ maxTotalExposure: (config.maxTotalExposure as number) ?? 500,
97
+ maxLossPerToken: config.maxLossPerToken as number | undefined,
98
+ maxDailyLoss: config.maxDailyLoss as number | undefined,
99
+ };
100
+
101
+ // Track current prices for risk calculations
102
+ const currentPrices = new Map<string, number>();
103
+
104
+ // 5. Process each signal
79
105
  for (const signal of signals) {
80
106
  try {
81
107
  // Check dedup
@@ -95,6 +121,11 @@ export async function runScanner(
95
121
  // Get market data for pricing
96
122
  const data = await marketData.getMarketData(signal.tokenId);
97
123
 
124
+ // Track price for risk calc
125
+ if (data.midpoint !== null) {
126
+ currentPrices.set(signal.tokenId, data.midpoint);
127
+ }
128
+
98
129
  // Calculate price
99
130
  const price = strategy.calculatePrice(signal, data, config);
100
131
 
@@ -105,6 +136,27 @@ export async function runScanner(
105
136
  // Determine order size
106
137
  const size = (config.orderSize as number) ?? 5;
107
138
 
139
+ // Check risk limits before placing
140
+ const riskCheck = checkOrderRisk(
141
+ inventories,
142
+ {
143
+ tokenId: signal.tokenId,
144
+ side: signal.side,
145
+ size,
146
+ price,
147
+ },
148
+ riskLimits,
149
+ currentPrices
150
+ );
151
+
152
+ if (!riskCheck.allowed) {
153
+ result.ordersSkippedRisk++;
154
+ result.errors.push(
155
+ `Risk limit blocked ${signal.label}: ${riskCheck.reason}`
156
+ );
157
+ continue;
158
+ }
159
+
108
160
  // Place order via OrderManager (handles live vs paper routing)
109
161
  const orderResult = await orderManager.placeOrder({
110
162
  slug: signal.slug,