1+ // -------------------------------------------------------------------------------
2+ // Displays projected equity at a draggable price line.
3+ // Takes into account P&L of open trades in the current symbol.
4+ // You can hide/show the line by pressing Shift+E.
5+ //
6+ // Version 1.00
7+ // Copyright 2025, EarnForex.com
8+ // https://www.earnforex.com/indicators/Entry-Line/
9+ // -------------------------------------------------------------------------------
10+
11+ using System ;
12+ using System . Linq ;
13+ using cAlgo . API ;
14+ using cAlgo . API . Internals ;
15+
16+ namespace cAlgo
17+ {
18+ [ Indicator ( IsOverlay = true , TimeZone = TimeZones . UTC , AccessRights = AccessRights . None ) ]
19+ public class EquityProjectionLine : Indicator
20+ {
21+ [ Parameter ( "Update Frequency (seconds)" , DefaultValue = 1 , MinValue = 1 ) ]
22+ public int UpdateFrequency { get ; set ; }
23+
24+ [ Parameter ( "Projection Line Color" , DefaultValue = "DodgerBlue" ) ]
25+ public Color LineColor { get ; set ; }
26+
27+ [ Parameter ( "Projection Line Width" , DefaultValue = 2 , MinValue = 1 ) ]
28+ public int LineWidth { get ; set ; }
29+
30+ [ Parameter ( "Projection Line Style" , DefaultValue = LineStyle . Solid ) ]
31+ public LineStyle LineStyleParam { get ; set ; }
32+
33+ [ Parameter ( "Show Equity Label" , DefaultValue = true ) ]
34+ public bool ShowLabel { get ; set ; }
35+
36+ [ Parameter ( "Equity Label Prefix" , DefaultValue = "EQUITY: " ) ]
37+ public string EquityLabelPrefix { get ; set ; }
38+
39+ [ Parameter ( "Label PositiveChange Color" , DefaultValue = "Green" ) ]
40+ public Color LabelPositiveChangeColor { get ; set ; }
41+
42+ [ Parameter ( "Label Negative Change Color" , DefaultValue = "Red" ) ]
43+ public Color LabelNegativeChangeColor { get ; set ; }
44+
45+ [ Parameter ( "Initial Price Offset (pips)" , DefaultValue = 50 ) ]
46+ public double InitialPriceOffset { get ; set ; }
47+
48+ // Global variables:
49+ private const string LineObjectName = "EquityProjectionLine" ;
50+ private const string EquityLabelObjectName = "EquityProjectionLabel" ;
51+ private ChartHorizontalLine projectionLine ;
52+ private ChartText equityLabel ;
53+ private double projectionPrice = 0 ;
54+ private double projectedEquity = 0 ;
55+ private bool isVisible = true ;
56+
57+ protected override void Initialize ( )
58+ {
59+ // Check if the line already exists.
60+ projectionLine = Chart . FindObject ( LineObjectName ) as ChartHorizontalLine ;
61+
62+ if ( projectionLine == null ) // If the line doesn't exist yet.
63+ {
64+ // Initialize projection price near current price.
65+ projectionPrice = Symbol . Bid + ( InitialPriceOffset * Symbol . PipSize ) ;
66+ projectionPrice = Math . Round ( projectionPrice , Symbol . Digits ) ;
67+
68+ DrawProjectionLine ( ) ;
69+ }
70+ else
71+ {
72+ projectionPrice = projectionLine . Y ;
73+ }
74+
75+ CalculateProjectedEquity ( ) ;
76+
77+ // Set up timer for updates.
78+ Timer . Start ( TimeSpan . FromSeconds ( UpdateFrequency ) ) ;
79+
80+ // Subscribe to chart events.
81+ Chart . ObjectsUpdated += OnChartObjectsUpdated ;
82+ Chart . KeyDown += OnChartKeyDown ;
83+ Chart . ScrollChanged += OnChartScrollChanged ;
84+ Chart . ZoomChanged += OnChartZoomChanged ;
85+ }
86+
87+ public override void Calculate ( int index )
88+ {
89+ CalculateProjectedEquity ( ) ;
90+ }
91+
92+ protected override void OnTimer ( )
93+ {
94+ CalculateProjectedEquity ( ) ;
95+ }
96+
97+ private void OnChartObjectsUpdated ( ChartObjectsUpdatedEventArgs obj )
98+ {
99+ if ( obj . Chart . FindObject ( LineObjectName ) is ChartHorizontalLine line )
100+ {
101+ if ( Math . Abs ( line . Y - projectionPrice ) > Symbol . TickSize )
102+ {
103+ projectionPrice = Math . Round ( line . Y , Symbol . Digits ) ;
104+ CalculateProjectedEquity ( ) ;
105+ UpdateLabel ( ) ;
106+ }
107+ }
108+ }
109+
110+ private void OnChartKeyDown ( ChartKeyboardEventArgs obj )
111+ {
112+ // Toggle visibility with Shift+E.
113+ if ( obj . Key == Key . E && ( obj . ShiftKey ) )
114+ {
115+ isVisible = ! isVisible ;
116+ ToggleVisibility ( ) ;
117+ }
118+ }
119+
120+ private void OnChartScrollChanged ( ChartScrollEventArgs obj )
121+ {
122+ UpdateLabel ( ) ;
123+ }
124+
125+ private void OnChartZoomChanged ( ChartZoomEventArgs obj )
126+ {
127+ UpdateLabel ( ) ;
128+ }
129+
130+ private void CalculateProjectedEquity ( )
131+ {
132+ // Get current account information.
133+ double currentEquity = Account . Equity ;
134+
135+ // Calculate total P&L change for positions in current symbol.
136+ double totalPLChange = 0 ;
137+
138+ // Get all positions for current symbol.
139+ var symbolPositions = Positions . Where ( p => p . SymbolName == Symbol . Name ) ;
140+
141+ foreach ( var position in symbolPositions )
142+ {
143+ double posLots = position . VolumeInUnits ;
144+
145+ // Calculate point value for this position.
146+ double pointValue = Symbol . PipValue * position . VolumeInUnits / Symbol . LotSize ;
147+
148+ // Calculate projected P&L at projection price.
149+ double projectedPL = 0 ;
150+
151+ if ( position . TradeType == TradeType . Buy )
152+ {
153+ double priceDiff = projectionPrice - Symbol . Bid ;
154+ // Convert price difference to pips and calculate P&L.
155+ projectedPL = ( priceDiff / Symbol . PipSize ) * pointValue ;
156+ }
157+ else // Sell position.
158+ {
159+ // For sell positions, we need to account for spread.
160+ double spread = Symbol . Ask - Symbol . Bid ;
161+ double projectedAsk = projectionPrice + spread ;
162+ double priceDiff = Symbol . Ask - projectedAsk ;
163+ // Convert price difference to pips and calculate P&L.
164+ projectedPL = ( priceDiff / Symbol . PipSize ) * pointValue ;
165+ }
166+
167+ totalPLChange += projectedPL ;
168+ }
169+
170+ // Calculate projected equity.
171+ projectedEquity = currentEquity + totalPLChange ;
172+
173+ // Update display.
174+ UpdateLabel ( ) ;
175+ }
176+
177+ private void DrawProjectionLine ( )
178+ {
179+ if ( projectionPrice <= 0 ) return ;
180+
181+ // Remove existing line if it exists.
182+ if ( projectionLine != null )
183+ {
184+ Chart . RemoveObject ( LineObjectName ) ;
185+ }
186+
187+ // Create new horizontal line.
188+ projectionLine = Chart . DrawHorizontalLine (
189+ LineObjectName ,
190+ projectionPrice ,
191+ LineColor ,
192+ LineWidth ,
193+ LineStyleParam
194+ ) ;
195+
196+ projectionLine . IsInteractive = true ;
197+ projectionLine . Comment = "Drag to change projection price" ;
198+
199+ // Add or update label.
200+ UpdateLabel ( ) ;
201+ }
202+
203+ private void UpdateLabel ( )
204+ {
205+ if ( projectionPrice <= 0 || ! ShowLabel ) return ;
206+
207+ // Ensure line exists.
208+ if ( projectionLine == null || Chart . FindObject ( LineObjectName ) == null )
209+ {
210+ DrawProjectionLine ( ) ;
211+ }
212+
213+ // Remove existing label.
214+ if ( equityLabel != null )
215+ {
216+ Chart . RemoveObject ( EquityLabelObjectName ) ;
217+ }
218+
219+ // Format equity text with proper decimal places.
220+ string equityText = EquityLabelPrefix + projectedEquity . ToString ( "F2" ) ;
221+
222+ // Calculate color based on equity change.
223+ double currentEquity = Account . Equity ;
224+ Color equityColor = LineColor ;
225+ if ( projectedEquity > currentEquity )
226+ equityColor = LabelPositiveChangeColor ;
227+ else if ( projectedEquity < currentEquity )
228+ equityColor = LabelNegativeChangeColor ;
229+
230+ // Get the leftmost visible bar index.
231+ int firstVisibleBar = Chart . FirstVisibleBarIndex ;
232+
233+ // Create label at the left side of the chart.
234+ equityLabel = Chart . DrawText (
235+ EquityLabelObjectName ,
236+ equityText ,
237+ firstVisibleBar ,
238+ projectionPrice ,
239+ equityColor
240+ ) ;
241+
242+ equityLabel . FontSize = 12 ;
243+ equityLabel . HorizontalAlignment = HorizontalAlignment . Right ;
244+ equityLabel . VerticalAlignment = VerticalAlignment . Top ;
245+ equityLabel . IsInteractive = false ;
246+ }
247+
248+ private void ToggleVisibility ( )
249+ {
250+ if ( isVisible )
251+ {
252+ // Hide objects.
253+ if ( projectionLine != null )
254+ {
255+ projectionLine . IsHidden = true ;
256+ }
257+ if ( equityLabel != null )
258+ {
259+ equityLabel . IsHidden = true ;
260+ }
261+ }
262+ else
263+ {
264+ // Show objects.
265+ if ( projectionLine != null )
266+ {
267+ projectionLine . IsHidden = false ;
268+ }
269+ if ( equityLabel != null )
270+ {
271+ equityLabel . IsHidden = false ;
272+ }
273+ }
274+ }
275+ }
276+ }
277+ //+------------------------------------------------------------------+
0 commit comments