Untitled
unknown
plain_text
10 months ago
14 kB
6
Indexable
using System;
using System.ComponentModel;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
namespace cAlgo.Robots
{
[Robot(AccessRights = AccessRights.FullAccess, AddIndicators = true, TimeZone = TimeZones.EasternStandardTime)]
public class ScalpingUtec : Robot
{
[Parameter("Hour End", Group = "Box", DefaultValue = 9)]
public int HourEnd { get; set; }
[Parameter("Minute End", Group = "Box", DefaultValue = 29)]
public int MinuteEnd { get; set; }
[Parameter("Hour End", Group = "Destroy Limit", DefaultValue = 9)]
public int LimitHourEnd { get; set; }
[Parameter("Minute End", Group = "Destroy Limit", DefaultValue = 29)]
public int LimitMinuteEnd { get; set; }
[Parameter("Hour End", Group = "Destroy Position", DefaultValue = 19)]
public int PositionHourEnd { get; set; }
[Parameter("Minute End", Group = "Destroy Position", DefaultValue = 00)]
public int PositionMinuteEnd { get; set; }
[Parameter("Hour End", Group = "Ending Session", DefaultValue = 9)]
public int SessionHourEnd { get; set; }
[Parameter("Minute End", Group = "Ending Session", DefaultValue = 29)]
public int SessionMinuteEnd { get; set; }
[Parameter("Look Back Bars", Group = "Box", DefaultValue = 89)]
public int BoxLookBackBars { get; set; }
[Parameter("Breaker After Cont Bars", Group = "Box", DefaultValue = 2)]
public int breakerAfterBoxBars { get; set; }
[Parameter("Breaker After Reve Bars", Group = "Box", DefaultValue = 21)]
public int breakerAfterBoxReversalBars { get; set; }
[Parameter("RR", Group = "Risk", DefaultValue = 2)]
public double RR { get; set; }
[Parameter("SL Gap", Group = "Risk", DefaultValue = 50)]
public double stoplossPipsGap { get; set; }
[Parameter("Risk percent", Group = "Risk", DefaultValue = 1)]
public double riskPercent { get; set; }
[Parameter("Apply Balance", Group = "Risk", DefaultValue = 3000)]
public double applyBalance { get; set; }
[Parameter("Max Limit State", Group = "Risk", DefaultValue = 4)]
public double maxLimitState { get; set; }
[Parameter("Max Position State", Group = "Risk", DefaultValue = 2)]
public double maxPositionState { get; set; }
// PRIVATE
private double boxHigh, boxLow;
private bool isBoxForming = false;
private bool isRunSearching = false;
private bool isKillSession = false;
private string breakerSide = "none";
private string caseBias = "none";
private double EntryPrice, StoplossPips;
//private int _breakerAfterBoxBarsCount = 0;
private int _positionOpenedCount = 0;
private int[] _minutesBreakerContinue = { 30, 31 };
private int[] _minutesBreakerReversal = { 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50 };
protected override void OnStart()
{
boxHigh = double.MinValue; boxLow = double.MaxValue;
Positions.Opened += OnPositionOpened;
}
private void OnPositionOpened(PositionOpenedEventArgs args)
{
Print("What Opened");
_positionOpenedCount++;
}
protected override void OnBar()
{
// Handle price updates here
DateTime lastBarTime = Bars.OpenTimes.Last(1);
Chart.DrawStaticText(
"dashboard_minix",
$"-- Now {lastBarTime.Hour}:{lastBarTime.Minute} \n" +
$"-- Position items {_positionOpenedCount} \n" +
$"-- Limit items {PendingOrders.Where(pod => pod.SymbolName == Symbol.Name).Count()} \n" +
($"-- Box High {boxHigh} | Low {boxLow} \n") +
$"-- Break Side {breakerSide} \n" +
$"-- case Bias {caseBias} \n" +
$"-- Goodbye Folk ? {isKillSession} \n"
,
VerticalAlignment.Bottom,
HorizontalAlignment.Left,
API.Color.OrangeRed
);
// --- Start Game Preprocessing ---
if (_positionOpenedCount >= maxPositionState)
{
// Destroy all pending
isKillSession = true;
deleteAllPendingOrders();
}
// 10:00 AM - No finding new trade
if ((lastBarTime.Hour > LimitHourEnd) || (lastBarTime.Hour == SessionHourEnd && lastBarTime.Minute >= SessionMinuteEnd))
{
// Destroy all pending
isKillSession = true;
deleteAllPendingOrders();
// caseBias | breakerSide | boxHigh |boxLow | isBoxForming -- khởi tạo mình gán nó value gì thì giờ mình gõ lại value đấy! a test kĩ lại giúp nha, có thể e sai!
isBoxForming = false;
isRunSearching = false;
isKillSession = false;
breakerSide = "none";
caseBias = "none";
boxHigh = double.MinValue;
boxLow = double.MaxValue;
_positionOpenedCount = 0;
}
// Kill Postition at 19:00
if(lastBarTime.Hour == PositionHourEnd && lastBarTime.Minute == PositionMinuteEnd) {
closeAllPositions();
}
// --- End Game Preprocessing ---
// Game Start Here
// =================== LET GO ===================
// Wait Box Forming - finding box at 9.30 (now is 9.30) Bars.OpenTime.Last(1) = 9.30 | Bars.OpenTime.Last(2) = 9.29
if (lastBarTime.Hour == HourEnd && lastBarTime.Minute == MinuteEnd + 1)
{
isKillSession = false;
for (int i = 2; i <= BoxLookBackBars + 1; i++)
{
boxHigh = Math.Max(boxHigh, Bars.HighPrices.Last(i));
boxLow = Math.Min(boxLow, Bars.LowPrices.Last(i));
}
isBoxForming = true;
}
// Bars.OpenTime.Last(1) = 9.30 | 9.31 with breakerAfterBoxBars = 2
// Wait for Breaker box -- Case Continue
// _breakerAfterBoxBarsCount = 0 --> [1,2]
// Case Continue thì mô tả xuôi checkvar 30 31 tại phút Last(1) = 30
if (isBoxForming && _minutesBreakerContinue.Contains(lastBarTime.Minute))
{
if (Bars.HighPrices.Last(1) > boxHigh && breakerSide == "none")
{
breakerSide = "top";
isRunSearching = true;
}
if (Bars.LowPrices.Last(1) < boxLow && breakerSide == "none")
{
breakerSide = "bottom";
isRunSearching = true;
}
if (isRunSearching)
{
caseBias = "Continue";
}
}
if (isBoxForming && breakerSide == "none")
{
// 9.29 (29 + 21bars = 50) | Heyyy now is 9.51 ; Last(1) = 9.51
if (lastBarTime.Hour == HourEnd && lastBarTime.Minute == 51) // Phut 51
{
// look back to 9.50 --> 9.32 (range 19 bars) , break or not ?
for (int i = 2; i <= 20; i++)
{
if (Bars.HighPrices.Last(i) > boxHigh)
{
breakerSide = "top";
isRunSearching = true;
}
if (Bars.LowPrices.Last(i) < boxLow)
{
breakerSide = "bottom";
isRunSearching = true;
}
}
if (isRunSearching)
{
caseBias = "Reversal";
}
}
}
if (isKillSession)
{
return;
}
if (!isRunSearching) return;
if (!this.IsImFvgBuy() && !this.IsImFvgSell()) { return; }
if (caseBias == "Continue")
{
if (breakerSide == "top" && this.IsImFvgBuy())
{
// Bias BUY
EntryPrice = Math.Min(Bars.OpenPrices.Last(1), Bars.ClosePrices.Last(1)) + 3;
StoplossPips = convertToPips(Math.Abs(EntryPrice - Bars.LowPrices.Last(3))) + stoplossPipsGap;
double lots = this.getRiskLots(StoplossPips, this.riskPercent);
PlaceLimitOrder(
TradeType.Buy,
SymbolName,
Symbol.QuantityToVolumeInUnits(lots),
EntryPrice,
"continue-buy-" + Bars.Count,
StoplossPips,
StoplossPips * RR
);
Print(" --- --- BUY LIMIT --- --- ");
}
if (breakerSide == "bottom" && this.IsImFvgSell())
{
EntryPrice = Math.Max(Bars.OpenPrices.Last(1), Bars.ClosePrices.Last(1)) - 3;
StoplossPips = convertToPips(Math.Abs(EntryPrice - Bars.HighPrices.Last(3))) + stoplossPipsGap;
double lots = this.getRiskLots(StoplossPips, this.riskPercent);
PlaceLimitOrder(
TradeType.Sell,
SymbolName,
Symbol.QuantityToVolumeInUnits(lots),
EntryPrice,
"continue-sell-" + Bars.Count,
StoplossPips,
StoplossPips * RR
);
Print(" --- --- SELL LIMIT --- --- ");
}
}
if (caseBias == "Reversal")
{
if (breakerSide == "bottom" && this.IsImFvgBuy())
{
// Bias BUY
EntryPrice = Math.Min(Bars.OpenPrices.Last(1), Bars.ClosePrices.Last(1)) + 3;
StoplossPips = convertToPips(Math.Abs(EntryPrice - Bars.LowPrices.Last(3))) + stoplossPipsGap;
double lots = this.getRiskLots(StoplossPips, this.riskPercent);
PlaceLimitOrder(
TradeType.Buy,
SymbolName,
Symbol.QuantityToVolumeInUnits(lots),
EntryPrice,
"reversal-buy-" + Bars.Count,
StoplossPips,
StoplossPips * RR
);
Print(" --- --- BUY LIMIT --- --- ");
}
if (breakerSide == "top" && this.IsImFvgSell())
{
EntryPrice = Math.Max(Bars.OpenPrices.Last(1), Bars.ClosePrices.Last(1)) - 3;
StoplossPips = convertToPips(Math.Abs(EntryPrice - Bars.HighPrices.Last(3))) + stoplossPipsGap;
double lots = this.getRiskLots(StoplossPips, this.riskPercent);
PlaceLimitOrder(
TradeType.Sell,
SymbolName,
Symbol.QuantityToVolumeInUnits(lots),
EntryPrice,
"reversal-sell-" + Bars.Count,
StoplossPips,
StoplossPips * RR
);
Print(" --- --- SELL LIMIT --- --- ");
}
}
}
protected override void OnTick()
{
}
protected override void OnStop()
{
// Handle cBot stop here
}
private double getRiskLots(double stopLossPips = 20, double riskPercentage = 1)
{
return Symbol.VolumeInUnitsToQuantity(Symbol.NormalizeVolumeInUnits(
this.getRiskCash(riskPercentage) / (stopLossPips * Symbol.PipValue)
));
}
private double getRiskCash(double riskPercentage)
{
return riskPercentage * 0.01 * this.getBalance();
}
private double getBalance()
{
return this.applyBalance;
}
private void deleteAllPendingOrders()
{
// Loop through each pending order and delete it
foreach (var pod in PendingOrders.Where(pod => pod.SymbolName == Symbol.Name))
{
CancelPendingOrder(pod);
}
}
private void closeAllPositions()
{
Print("** closeAllPositions");
foreach (var pos in Positions.Where(pos => pos.SymbolName == Symbol.Name))
{
ClosePositionAsync(pos);
}
}
private bool IsImFvgBuy()
{
bool check1 = Bars.LowPrices.Last(1) > Math.Max(Bars.OpenPrices.Last(3), Bars.ClosePrices.Last(3));
bool check2 = Bars.HighPrices.Last(3) < Math.Min(Bars.OpenPrices.Last(1), Bars.ClosePrices.Last(1));
return check1 && check2;
}
private bool IsImFvgSell()
{
bool check1 = Bars.HighPrices.Last(1) < Math.Min(Bars.OpenPrices.Last(3), Bars.ClosePrices.Last(3));
bool check2 = Bars.HighPrices.Last(3) > Math.Max(Bars.OpenPrices.Last(1), Bars.ClosePrices.Last(1));
return check1 && check2;
}
private double convertToPips(double priceDif)
{
return Math.Round(Math.Abs(priceDif / Symbol.PipSize), 1);
}
}
}Editor is loading...
Leave a Comment