Skip to content

Commit 6b0c35f

Browse files
authored
Merge pull request #556 from JChinaM/master
new robot BreakLRTrailVolatility
2 parents 5de864a + 9dc3e7c commit 6b0c35f

File tree

2 files changed

+348
-6
lines changed

2 files changed

+348
-6
lines changed
Lines changed: 342 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,342 @@
1+
using OsEngine.Charts.CandleChart.Indicators;
2+
using OsEngine.Entity;
3+
using OsEngine.Indicators;
4+
using OsEngine.OsTrader.Panels;
5+
using OsEngine.OsTrader.Panels.Attributes;
6+
using OsEngine.OsTrader.Panels.Tab;
7+
using System;
8+
using System.Collections.Generic;
9+
10+
/* Description
11+
trading robot for osengine
12+
13+
The trend robot on BreakLRTrailVolatility.
14+
15+
Buy: the price is above the upper LR line.
16+
17+
Sale: the price is below the lower LR line.
18+
19+
Exit from a long position: The trailing stop is placed at the minimum –Atr * Er for the period specified for the
20+
trailing stop and is transferred, (slides), to new price lows, also for the specified period.
21+
22+
Exit from the short position: The trailing stop is placed at the maximum +Atr * Er for the period specified for the
23+
trailing stop and is transferred (slides) to the new maximum of the price, also for the specified period.
24+
25+
*/
26+
27+
28+
namespace OsEngine.Robots.CMO
29+
{
30+
[Bot("BreakLRTrailVolatility")] // We create an attribute so that we don't write anything to the BotFactory
31+
public class BreakLRTrailVolatility : BotPanel
32+
{
33+
private BotTabSimple _tab;
34+
35+
// Basic Settings
36+
private StrategyParameterString Regime;
37+
private StrategyParameterString VolumeRegime;
38+
private StrategyParameterDecimal VolumeOnPosition;
39+
private StrategyParameterDecimal Slippage;
40+
private StrategyParameterTimeOfDay StartTradeTime;
41+
private StrategyParameterTimeOfDay EndTradeTime;
42+
43+
// Indicator setting
44+
private StrategyParameterInt LengthATR;
45+
private StrategyParameterInt LrLength;
46+
private StrategyParameterDecimal UpDeviation;
47+
private StrategyParameterDecimal DownDeviation;
48+
private StrategyParameterInt LengthER;
49+
50+
// Indicator
51+
Aindicator _ATR;
52+
Aindicator _LR;
53+
Aindicator _ER;
54+
55+
// Exit
56+
private StrategyParameterInt TrailCandlesLong;
57+
private StrategyParameterInt TrailCandlesShort;
58+
59+
// The last value of the indicator
60+
private decimal _lastATR;
61+
private decimal _lastLrUp;
62+
private decimal _lastLrDown;
63+
private decimal _lastER;
64+
65+
public BreakLRTrailVolatility(string name, StartProgram startProgram) : base(name, startProgram)
66+
{
67+
TabCreate(BotTabType.Simple);
68+
_tab = TabsSimple[0];
69+
70+
// Basic setting
71+
Regime = CreateParameter("Regime", "Off", new[] { "Off", "On", "OnlyLong", "OnlyShort", "OnlyClosePosition" }, "Base");
72+
VolumeRegime = CreateParameter("Volume type", "Number of contracts", new[] { "Number of contracts", "Contract currency" }, "Base");
73+
VolumeOnPosition = CreateParameter("Volume", 1, 1.0m, 50, 4, "Base");
74+
Slippage = CreateParameter("Slippage %", 0m, 0, 20, 1, "Base");
75+
StartTradeTime = CreateParameterTimeOfDay("Start Trade Time", 0, 0, 0, 0, "Base");
76+
EndTradeTime = CreateParameterTimeOfDay("End Trade Time", 24, 0, 0, 0, "Base");
77+
78+
// Indicator setting
79+
LengthATR = CreateParameter("ATR Length", 14, 7, 48, 7, "Indicator");
80+
LrLength = CreateParameter("LR Length", 10, 10, 300, 10, "Indicator");
81+
UpDeviation = CreateParameter("Up Deviation", 3.0m, 1, 5, 0.1m, "Indicator");
82+
DownDeviation = CreateParameter("Down Deviation", 3.0m, 1, 5, 0.1m, "Indicator");
83+
LengthER = CreateParameter("LengthER", 20, 10, 300, 10, "Indicator");
84+
85+
// Create indicator LR
86+
_LR = IndicatorsFactory.CreateIndicatorByName("LinearRegressionChannel", name + "LinearRegressionChannel", false);
87+
_LR = (Aindicator)_tab.CreateCandleIndicator(_LR, "Prime");
88+
((IndicatorParameterInt)_LR.Parameters[0]).ValueInt = LrLength.ValueInt;
89+
((IndicatorParameterDecimal)_LR.Parameters[2]).ValueDecimal = UpDeviation.ValueDecimal;
90+
((IndicatorParameterDecimal)_LR.Parameters[3]).ValueDecimal = DownDeviation.ValueDecimal;
91+
_LR.Save();
92+
93+
// Create indicator ATR
94+
_ATR = IndicatorsFactory.CreateIndicatorByName("ATR", name + "ATR", false);
95+
_ATR = (Aindicator)_tab.CreateCandleIndicator(_ATR, "NewArea");
96+
((IndicatorParameterInt)_ATR.Parameters[0]).ValueInt = LengthATR.ValueInt;
97+
_ATR.Save();
98+
99+
// Create indicator EfficiencyRatio
100+
_ER = IndicatorsFactory.CreateIndicatorByName("EfficiencyRatio", name + "EfficiencyRatio", false);
101+
_ER = (Aindicator)_tab.CreateCandleIndicator(_ER, "NewArea0");
102+
((IndicatorParameterInt)_ER.Parameters[0]).ValueInt = LengthER.ValueInt;
103+
_ER.Save();
104+
105+
// Exit
106+
TrailCandlesLong = CreateParameter("Trail Candles Long", 5, 5, 200, 5, "Exit");
107+
TrailCandlesShort = CreateParameter("Trail Candles Short", 5, 5, 200, 5, "Exit");
108+
109+
// Subscribe to the indicator update event
110+
ParametrsChangeByUser += BreakLRTrailVolatility_ParametrsChangeByUser; ;
111+
112+
// Subscribe to the candle finished event
113+
_tab.CandleFinishedEvent += _tab_CandleFinishedEvent;
114+
115+
Description = "The trend robot on BreakLRTrailVolatility. " +
116+
"Buy: the price is above the upper LR line. " +
117+
"Sale: the price is below the lower LR line. " +
118+
"Exit from a long position: The trailing stop is placed at the minimum –Atr * Er for the period specified for the " +
119+
"trailing stop and is transferred, (slides), to new price lows, also for the specified period. " +
120+
"Exit from the short position: The trailing stop is placed at the maximum +Atr * Er for the period specified for the " +
121+
"trailing stop and is transferred (slides) to the new maximum of the price, also for the specified period.";
122+
}
123+
124+
private void BreakLRTrailVolatility_ParametrsChangeByUser()
125+
{
126+
((IndicatorParameterInt)_ATR.Parameters[0]).ValueInt = LengthATR.ValueInt;
127+
_ATR.Save();
128+
_ATR.Reload();
129+
((IndicatorParameterInt)_LR.Parameters[0]).ValueInt = LrLength.ValueInt;
130+
((IndicatorParameterDecimal)_LR.Parameters[2]).ValueDecimal = UpDeviation.ValueDecimal;
131+
((IndicatorParameterDecimal)_LR.Parameters[3]).ValueDecimal = DownDeviation.ValueDecimal;
132+
_LR.Save();
133+
_LR.Reload();
134+
((IndicatorParameterInt)_ER.Parameters[0]).ValueInt = LengthER.ValueInt;
135+
_ER.Save();
136+
_ER.Reload();
137+
}
138+
139+
// The name of the robot in OsEngine
140+
public override string GetNameStrategyType()
141+
{
142+
return "BreakLRTrailVolatility";
143+
}
144+
public override void ShowIndividualSettingsDialog()
145+
{
146+
147+
}
148+
149+
// Candle Finished Event
150+
private void _tab_CandleFinishedEvent(List<Candle> candles)
151+
{
152+
// If the robot is turned off, exit the event handler
153+
if (Regime.ValueString == "Off")
154+
{
155+
return;
156+
}
157+
158+
// If there are not enough candles to build an indicator, we exit
159+
if (candles.Count < LengthATR.ValueInt ||
160+
candles.Count < LengthER.ValueInt ||
161+
candles.Count < LrLength.ValueInt)
162+
{
163+
return;
164+
}
165+
166+
// If the time does not match, we leave
167+
if (StartTradeTime.Value > _tab.TimeServerCurrent ||
168+
EndTradeTime.Value < _tab.TimeServerCurrent)
169+
{
170+
return;
171+
}
172+
173+
List<Position> openPositions = _tab.PositionsOpenAll;
174+
175+
// If there are positions, then go to the position closing method
176+
if (openPositions != null && openPositions.Count != 0)
177+
{
178+
LogicClosePosition(candles);
179+
}
180+
181+
// If the position closing mode, then exit the method
182+
if (Regime.ValueString == "OnlyClosePosition")
183+
{
184+
return;
185+
}
186+
// If there are no positions, then go to the position opening method
187+
if (openPositions == null || openPositions.Count == 0)
188+
{
189+
LogicOpenPosition(candles);
190+
}
191+
}
192+
193+
// Opening logic
194+
private void LogicOpenPosition(List<Candle> candles)
195+
{
196+
// The last value of the indicator
197+
_lastATR = _ATR.DataSeries[0].Last;
198+
_lastLrUp = _LR.DataSeries[0].Last;
199+
_lastLrDown = _LR.DataSeries[2].Last;
200+
_lastER = _ER.DataSeries[0].Last;
201+
202+
List<Position> openPositions = _tab.PositionsOpenAll;
203+
204+
if (openPositions == null || openPositions.Count == 0)
205+
{
206+
decimal lastPrice = candles[candles.Count - 1].Close;
207+
208+
List<decimal> VolumeER = _ER.DataSeries[0].Values;
209+
List<decimal> VolumeCCI = _ATR.DataSeries[0].Values;
210+
211+
// Slippage
212+
decimal _slippage = Slippage.ValueDecimal * _tab.Securiti.PriceStep;
213+
214+
// Long
215+
if (Regime.ValueString != "OnlyShort") // If the mode is not only short, then we enter long
216+
{
217+
if(_lastLrUp < lastPrice)
218+
{
219+
_tab.BuyAtLimit(GetVolume(), _tab.PriceBestAsk + _slippage);
220+
}
221+
}
222+
223+
// Short
224+
if (Regime.ValueString != "OnlyLong") // If the mode is not only long, then we enter short
225+
{
226+
if(_lastLrDown > lastPrice)
227+
{
228+
_tab.SellAtLimit(GetVolume(), _tab.PriceBestBid - _slippage);
229+
}
230+
}
231+
}
232+
}
233+
234+
// Logic close position
235+
private void LogicClosePosition(List<Candle> candles)
236+
{
237+
List<Position> openPositions = _tab.PositionsOpenAll;
238+
239+
decimal _slippage = Slippage.ValueDecimal * _tab.Securiti.PriceStep;
240+
241+
// The last value of the indicator
242+
_lastER = _ER.DataSeries[0].Last;
243+
_lastATR = _ATR.DataSeries[0].Last;
244+
245+
for (int i = 0; openPositions != null && i < openPositions.Count; i++)
246+
{
247+
Position positions = openPositions[i];
248+
249+
if (positions.State != PositionStateType.Open)
250+
{
251+
continue;
252+
}
253+
254+
if (positions.Direction == Side.Buy) // If the direction of the position is purchase
255+
{
256+
decimal price = GetPriceStop(Side.Buy, candles, candles.Count - 1) - _lastATR * _lastER;
257+
if (price == 0)
258+
{
259+
return;
260+
}
261+
_tab.CloseAtTrailingStop(openPositions[0], price, price - _slippage);
262+
}
263+
else // If the direction of the position is sale
264+
{
265+
decimal price = GetPriceStop(Side.Sell, candles, candles.Count - 1) + _lastATR * _lastER;
266+
if (price == 0)
267+
{
268+
return;
269+
}
270+
_tab.CloseAtTrailingStop(openPositions[0], price, price + _slippage);
271+
}
272+
273+
}
274+
}
275+
276+
private decimal GetPriceStop(Side side, List<Candle> candles, int index)
277+
{
278+
if (candles == null || index < TrailCandlesLong.ValueInt || index < TrailCandlesShort.ValueInt)
279+
{
280+
return 0;
281+
}
282+
283+
if (side == Side.Buy)
284+
{
285+
decimal price = decimal.MaxValue;
286+
287+
for (int i = index; i > index - TrailCandlesLong.ValueInt; i--)
288+
{
289+
if (candles[i].Low < price)
290+
{
291+
price = candles[i].Low;
292+
}
293+
}
294+
return price;
295+
}
296+
297+
if (side == Side.Sell)
298+
{
299+
decimal price = 0;
300+
301+
for (int i = index; i > index - TrailCandlesShort.ValueInt; i--)
302+
{
303+
if (candles[i].High > price)
304+
{
305+
price = candles[i].High;
306+
}
307+
}
308+
309+
return price;
310+
}
311+
return 0;
312+
}
313+
314+
// Method for calculating the volume of entry into a position
315+
private decimal GetVolume()
316+
{
317+
decimal volume = 0;
318+
319+
if (VolumeRegime.ValueString == "Contract currency")
320+
{
321+
decimal contractPrice = _tab.PriceBestAsk;
322+
volume = VolumeOnPosition.ValueDecimal / contractPrice;
323+
}
324+
else if (VolumeRegime.ValueString == "Number of contracts")
325+
{
326+
volume = VolumeOnPosition.ValueDecimal;
327+
}
328+
329+
// If the robot is running in the tester
330+
if (StartProgram == StartProgram.IsTester)
331+
{
332+
volume = Math.Round(volume, 6);
333+
}
334+
else
335+
{
336+
volume = Math.Round(volume, _tab.Securiti.DecimalsVolume);
337+
}
338+
return volume;
339+
}
340+
}
341+
}
342+

project/OsEngine/bin/Debug/Custom/Robots/IntersectionOfROCAndAdaptiveLookBack.cs renamed to project/OsEngine/bin/Debug/Custom/Robots/StrategyAdaptiveLookBackAndROC.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ 2. ROC is below 0.
2525

2626
namespace OsEngine.Robots.My_bots
2727
{
28-
[Bot("IntersectionOfROCAndAdaptiveLookBack")] //We create an attribute so that we don't write anything in the Boot factory
29-
public class IntersectionOfROCAndAdaptiveLookBack : BotPanel
28+
[Bot("StrategyAdaptiveLookBackAndROC")] //We create an attribute so that we don't write anything in the Boot factory
29+
public class StrategyAdaptiveLookBackAndROC : BotPanel
3030

3131
{
3232
BotTabSimple _tab;
@@ -59,7 +59,7 @@ public class IntersectionOfROCAndAdaptiveLookBack : BotPanel
5959

6060

6161

62-
public IntersectionOfROCAndAdaptiveLookBack(string name, StartProgram startProgram) : base(name, startProgram)
62+
public StrategyAdaptiveLookBackAndROC(string name, StartProgram startProgram) : base(name, startProgram)
6363
{
6464
TabCreate(BotTabType.Simple);
6565
_tab = TabsSimple[0];
@@ -94,7 +94,7 @@ public IntersectionOfROCAndAdaptiveLookBack(string name, StartProgram startProgr
9494
((IndicatorParameterInt)ROC.Parameters[0]).ValueInt = LengthROC.ValueInt;
9595
ROC.DataSeries[0].Color = Color.Red;
9696
ROC.Save();
97-
ParametrsChangeByUser += IntersectionOfROCAndAdaptiveLookBack_ParametrsChangeByUser;
97+
ParametrsChangeByUser += StrategyAdaptiveLookBackAndROC_ParametrsChangeByUser;
9898

9999
// Subscribe to the candle finished event
100100
_tab.CandleFinishedEvent += _tab_CandleFinishedEvent;
@@ -108,7 +108,7 @@ public IntersectionOfROCAndAdaptiveLookBack(string name, StartProgram startProgr
108108
}
109109

110110
// Indicator Update event
111-
private void IntersectionOfROCAndAdaptiveLookBack_ParametrsChangeByUser()
111+
private void StrategyAdaptiveLookBackAndROC_ParametrsChangeByUser()
112112
{
113113
((IndicatorParameterInt)ALB.Parameters[0]).ValueInt = PeriodALB.ValueInt;
114114
ALB.Save();
@@ -121,7 +121,7 @@ private void IntersectionOfROCAndAdaptiveLookBack_ParametrsChangeByUser()
121121
// The name of the robot in OsEngine
122122
public override string GetNameStrategyType()
123123
{
124-
return "IntersectionOfROCAndAdaptiveLookBack";
124+
return "StrategyAdaptiveLookBackAndROC";
125125
}
126126
public override void ShowIndividualSettingsDialog()
127127
{

0 commit comments

Comments
 (0)