@@ -194,6 +194,51 @@ export class ForegroundGridBot {
194194 ) ;
195195 }
196196
197+ if (
198+ ! new Decimal ( existingState . config . investment ) . eq (
199+ this . _config . investment ,
200+ )
201+ ) {
202+ throw new Error (
203+ `Saved grid was started with investment ${ existingState . config . investment } ` +
204+ `but you requested ${ this . _config . investment } . ` +
205+ `Use --reset to discard saved state and start fresh.` ,
206+ ) ;
207+ }
208+
209+ if ( existingState . config . dryRun !== this . _config . dryRun ) {
210+ throw new Error (
211+ `Saved grid was started in ${ existingState . config . dryRun ? "dry-run" : "live" } mode ` +
212+ `but you requested ${ this . _config . dryRun ? "dry-run" : "live" } mode. ` +
213+ `Use --reset to discard saved state and start fresh.` ,
214+ ) ;
215+ }
216+
217+ if (
218+ Boolean ( existingState . config . trailingUp ) !== this . _config . trailingUp
219+ ) {
220+ throw new Error (
221+ `Saved grid was started ${ existingState . config . trailingUp ? "with" : "without" } --trailing-up ` +
222+ `but you requested ${ this . _config . trailingUp ? "with" : "without" } --trailing-up. ` +
223+ `Use --reset to discard saved state and start fresh.` ,
224+ ) ;
225+ }
226+
227+ const savedStopLoss = existingState . config . stopLoss ;
228+ const newStopLoss = this . _config . stopLoss ;
229+ const stopLossMismatch =
230+ ( savedStopLoss == null ) !== ( newStopLoss == null ) ||
231+ ( savedStopLoss != null &&
232+ newStopLoss != null &&
233+ ! new Decimal ( savedStopLoss ) . eq ( newStopLoss ) ) ;
234+ if ( stopLossMismatch ) {
235+ throw new Error (
236+ `Saved grid was started with stop-loss ${ savedStopLoss ?? "(none)" } ` +
237+ `but you requested ${ newStopLoss ?? "(none)" } . ` +
238+ `Use --reset to discard saved state and start fresh.` ,
239+ ) ;
240+ }
241+
197242 await this . _reconcileAndInit ( existingState ) ;
198243 } else {
199244 await this . _initNewGrid ( ) ;
@@ -1079,17 +1124,14 @@ export class ForegroundGridBot {
10791124 // Phase 1: Adopt saved state as-is
10801125 this . _state = savedState ;
10811126
1082- // Update mutable config fields (geometry + split validated in run())
1127+ // Update mutable config fields (everything else validated in run())
10831128 this . _state . config . intervalSec = config . intervalSec ;
1084- this . _state . config . dryRun = config . dryRun ;
10851129
10861130 const quoteStep = this . _getQuoteStep ( ) ;
10871131 const baseStep = this . _getBaseStep ( ) ;
10881132 this . _state . quotePrecision = quoteStep . toString ( ) ;
10891133 this . _state . basePrecision = baseStep . toString ( ) ;
10901134
1091- const newInvestment = new Decimal ( config . investment ) ;
1092-
10931135 // Phase 2: Verify each saved order against the exchange
10941136 let buysFilled = 0 ;
10951137 let sellsFilled = 0 ;
@@ -1210,27 +1252,6 @@ export class ForegroundGridBot {
12101252 }
12111253 }
12121254
1213- // Recalculate quotePerLevel if investment changed
1214- if ( config . investment !== this . _state . config . investment ) {
1215- const midPrice = await this . _getMidPrice ( ) ;
1216- const totalActiveLevels = this . _state . levels . filter (
1217- ( l ) =>
1218- l . buyOrderIds . length > 0 ||
1219- l . positions . length > 0 ||
1220- new Decimal ( l . price ) . lte ( midPrice ) ,
1221- ) . length ;
1222- const quotePerLevel = newInvestment
1223- . div ( Math . max ( totalActiveLevels , 1 ) )
1224- . toDecimalPlaces ( 2 , Decimal . ROUND_DOWN ) ;
1225- this . _state . quotePerLevel = quotePerLevel . toString ( ) ;
1226- this . _state . config . investment = config . investment ;
1227- console . log (
1228- chalk . dim (
1229- ` Investment changed: quote per level recalculated to ${ quotePerLevel } ` ,
1230- ) ,
1231- ) ;
1232- }
1233-
12341255 // Phase 3: Handle split mode
12351256 if (
12361257 config . splitInvestment &&
0 commit comments