@@ -41,5 +41,45 @@ export function compilePine(config: StrategyConfig): string {
4141 code = code . replace ( oldHtfBackground , profileAwareHtfBackground ) ;
4242 }
4343
44+ const hasVisualRisk = config . outputMode === "indicator" && ( config . risk . stopMode !== "none" || config . risk . takeProfitMode !== "none" ) ;
45+ if ( hasVisualRisk ) {
46+ const outcomeState = 'var string lastRiskOutcome = "NONE"' ;
47+ const outcomeStateWithPrices = `${ outcomeState } \nvar float lastOutcomeEntry = na\nvar float lastOutcomePrice = na` ;
48+ if ( ! code . includes ( outcomeState ) ) throw new Error ( "Compiler transform anchor missing: last risk outcome state" ) ;
49+ code = code . replace ( outcomeState , outcomeStateWithPrices ) ;
50+
51+ if ( code . includes ( 'lastRiskOutcome := "REVERSED"' ) ) {
52+ code = code . replace (
53+ 'lastRiskOutcome := "REVERSED"' ,
54+ 'lastRiskOutcome := "REVERSED"\n lastOutcomeEntry := riskEntry\n lastOutcomePrice := close'
55+ ) ;
56+ }
57+
58+ const outcomePriceAnchor = 'outcomePrice = riskAmbiguous ? math.avg(riskStop, riskTarget) : riskStopHit ? riskStop : riskTarget' ;
59+ if ( ! code . includes ( outcomePriceAnchor ) ) throw new Error ( "Compiler transform anchor missing: risk outcome price" ) ;
60+ code = code . replace (
61+ outcomePriceAnchor ,
62+ `${ outcomePriceAnchor } \n lastOutcomeEntry := riskEntry\n lastOutcomePrice := outcomePrice`
63+ ) ;
64+
65+ if ( config . execution . showDashboard ) {
66+ code = code . replace (
67+ / v a r t a b l e d a s h b o a r d = t a b l e \. n e w \( p o s i t i o n \. t o p _ r i g h t , 2 , ( \d + ) , b o r d e r _ w i d t h = 1 \) / ,
68+ ( _match , rows ) => `var table dashboard = table.new(position.top_right, 2, ${ Number ( rows ) + 2 } , border_width=1)`
69+ ) ;
70+
71+ const sessionValue = / t a b l e \. c e l l \( d a s h b o a r d , 1 , ( \d + ) , s e s s i o n O k \? " A C T I V E " : " C L O S E D " , t e x t _ c o l o r = s e s s i o n O k \? c o l o r \. l i m e : c o l o r \. g r a y \) / ;
72+ const resultValue = / t a b l e \. c e l l \( d a s h b o a r d , 1 , ( \d + ) , l a s t R i s k O u t c o m e , t e x t _ c o l o r = l a s t R i s k O u t c o m e = = " T A R G E T H I T " \? c o l o r \. l i m e : l a s t R i s k O u t c o m e = = " S T O P H I T " \? c o l o r \. r e d : l a s t R i s k O u t c o m e = = " N O N E " \? c o l o r \. g r a y : c o l o r \. o r a n g e \) / ;
73+ const match = code . match ( sessionValue ) ?? code . match ( resultValue ) ;
74+ if ( ! match ) throw new Error ( "Compiler transform anchor missing: dashboard final risk row" ) ;
75+
76+ const entryRow = Number ( match [ 1 ] ) + 1 ;
77+ const priceRow = entryRow + 1 ;
78+ const anchor = match [ 0 ] ;
79+ const replacement = `${ anchor } \n table.cell(dashboard, 0, ${ entryRow } , "Last entry")\n table.cell(dashboard, 1, ${ entryRow } , na(lastOutcomeEntry) ? "NONE" : str.tostring(lastOutcomeEntry, format.mintick), text_color=na(lastOutcomeEntry) ? color.gray : color.white)\n table.cell(dashboard, 0, ${ priceRow } , "Result price")\n table.cell(dashboard, 1, ${ priceRow } , na(lastOutcomePrice) ? "NONE" : str.tostring(lastOutcomePrice, format.mintick), text_color=lastRiskOutcome == "TARGET HIT" ? color.lime : lastRiskOutcome == "STOP HIT" ? color.red : lastRiskOutcome == "NONE" ? color.gray : color.orange)` ;
80+ code = code . replace ( anchor , replacement ) ;
81+ }
82+ }
83+
4484 return code ;
4585}
0 commit comments