Information
Username: | CoreTradingHouse |
Member since: | 05 Feb 2018 |
Last login: | 05 Feb 2018 |
Status: | Active |
Activity
Where | Created | Comments |
---|---|---|
Algorithms | 1 | 8 |
Forum Topics | 1 | 1 |
Jobs | 0 | 0 |
Last Algorithm Comments
@jumpycalm working on something new right now!
Added:
- 1 std BB
- 2 std BB
- Awesome oscillator
instead of opening trades, when ist overbought / sold, it places 3 stop orders with 1 day expiration. Then the grid is managed as usual.
Still has to be polished, but it seriously reduces DD. tell me what you think, and suggestions are accepted! :)
//------------------------------------------------------
using System;
using cAlgo.API;
using cAlgo.API.Indicators;
namespace cAlgo
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class SmartGrid : Robot
{
private bool _accountIsOutOfMoney;
private int _openTradeResult;
private readonly string Label = "SmartGrid2";
private DateTime _lastBuyTradeTime;
private DateTime _lastSellTradeTime;
[Parameter("Buy", DefaultValue = true)]
public bool Buy { get; set; }
[Parameter("Sell", DefaultValue = true)]
public bool Sell { get; set; }
[Parameter("Pip Step", DefaultValue = 10, MinValue = 1)]
public int PipStep { get; set; }
[Parameter("First Volume", DefaultValue = 1000, MinValue = 1000, Step = 1000)]
public int FirstVolume { get; set; }
[Parameter("Volume Exponent", DefaultValue = 1.0, MinValue = 0.1, MaxValue = 5.0)]
public double VolumeExponent { get; set; }
[Parameter("Max Spread", DefaultValue = 3.0)]
public double MaxSpread { get; set; }
[Parameter("Average TP", DefaultValue = 3, MinValue = 1)]
public int AverageTakeProfit { get; set; }
[Parameter("BB_Source")]
public DataSeries BB_Source { get; set; }
[Parameter("BandPeriods", DefaultValue = 20)]
public int BB_BandPeriod { get; set; }
[Parameter("Std", DefaultValue = 1)]
public int BB_std { get; set; }
[Parameter("MAType")]
public MovingAverageType BB_MAType { get; set; }
[Parameter("BB2_Source")]
public DataSeries BB2_Source { get; set; }
[Parameter("BandPeriods", DefaultValue = 20)]
public int BB2_BandPeriod { get; set; }
[Parameter("Std", DefaultValue = 2)]
public int BB2_std { get; set; }
[Parameter("MAType")]
public MovingAverageType BB2_MAType { get; set; }
private double CurrentSpread
{
get { return (Symbol.Ask - Symbol.Bid) / Symbol.PipSize; }
}
private BollingerBands BB_boll;
private BollingerBands BB_2boll;
private AwesomeOscillator awesomeOscillator;
protected override void OnStart()
{
BB_boll = Indicators.BollingerBands(BB_Source, BB_BandPeriod, BB_std, BB_MAType);
BB_2boll = Indicators.BollingerBands(BB2_Source, BB2_BandPeriod, BB2_std, BB2_MAType);
awesomeOscillator = Indicators.AwesomeOscillator();
}
protected override void OnBar()
{
//indicators();
//ProcessTrades_NEW();
if (CountOfTradesOfType(TradeType.Buy) > 2)
AdjustBuyPositionTakeProfits(CalculateAveragePositionPrice(TradeType.Buy), AverageTakeProfit);
if (CountOfTradesOfType(TradeType.Sell) > 2)
AdjustSellPositionTakeProfits(CalculateAveragePositionPrice(TradeType.Sell), AverageTakeProfit);
if (CurrentSpread <= MaxSpread && !_accountIsOutOfMoney)
ProcessTrades_NEW();
RefreshData();
if (!this.IsBacktesting)
DisplayStatusOnChart();
}
protected override void OnError(Error error)
{
if (error.Code == ErrorCode.NoMoney)
{
_accountIsOutOfMoney = true;
Print("opening stopped because: not enough money");
}
}
// protected override void OnBar()
// {
//}
protected override void OnStop()
{
ChartObjects.RemoveAllObjects();
}
//------------------------------------------------------------------------------------------------------------
private void ProcessTrades_NEW()
{
DateTime expiration = Server.Time.AddDays(1);
var AO = Math.Round(awesomeOscillator.Result.Last(0), 5);
var AO_last = Math.Round(awesomeOscillator.Result.Last(1), 5);
var direction = 0;
if (!this.IsBacktesting)
{
ChartObjects.DrawText("DIR", " " + direction, StaticPosition.TopCenter, Colors.White);
}
var BB2_top = Math.Round(BB_2boll.Top.LastValue, 5);
//BB2 top
var BB_top = Math.Round(BB_boll.Top.LastValue, 5);
//BB top
var mid = Math.Round(BB_boll.Main.LastValue, 5);
//BB mid
var BB_bottom = Math.Round(BB_boll.Bottom.LastValue, 5);
//BB bottom
var BB2_bottom = Math.Round(BB_2boll.Bottom.LastValue, 5);
//BB2 bottom
var TP_CALC = Math.Round((BB2_top - BB2_bottom) / Symbol.PipSize, 1);
if (!this.IsBacktesting)
{
ChartObjects.DrawText("DIR", " " + direction + "|" + TP_CALC, StaticPosition.TopCenter, Colors.White);
}
if (AO < AO_last && AO > 0 && AO_last > 0 && Symbol.Bid > mid)
{
direction = -1;
if (!this.IsBacktesting)
{
ChartObjects.DrawText("DIR", "SELL " + direction + "|" + TP_CALC, StaticPosition.TopCenter, Colors.White);
}
}
if (AO > AO_last && AO < 0 && AO_last < 0 && Symbol.Ask < mid)
{
direction = 1;
if (!this.IsBacktesting)
{
ChartObjects.DrawText("DIR", "BUY " + direction + "|" + TP_CALC, StaticPosition.TopCenter, Colors.White);
}
}
// send buy orders
if (direction == 1)
{
if (Math.Round(Symbol.Ask, Symbol.Digits) < Math.Round(FindLowestPositionPrice(TradeType.Buy) - PipStep * Symbol.PipSize, Symbol.Digits))
{
var calculatedVolume = CalculateVolume(TradeType.Buy);
PlaceStopOrder(TradeType.Buy, Symbol, LimitVolume(calculatedVolume), BB_bottom, Label, 0, TP_CALC, expiration);
PlaceStopOrder(TradeType.Buy, Symbol, LimitVolume(calculatedVolume), mid, Label, 0, TP_CALC, expiration);
PlaceStopOrder(TradeType.Buy, Symbol, LimitVolume(calculatedVolume), BB_top, Label, 0, TP_CALC, expiration);
}
}
// send SELL orders
if (direction == -1)
{
if (Math.Round(Symbol.Bid, Symbol.Digits) > Math.Round(FindHighestPositionPrice(TradeType.Sell) + PipStep * Symbol.PipSize, Symbol.Digits))
{
var calculatedVolume = CalculateVolume(TradeType.Sell);
PlaceStopOrder(TradeType.Sell, Symbol, LimitVolume(calculatedVolume), BB_bottom, Label, 0, TP_CALC, expiration);
PlaceStopOrder(TradeType.Sell, Symbol, LimitVolume(calculatedVolume), mid, Label, 0, TP_CALC, expiration);
PlaceStopOrder(TradeType.Sell, Symbol, LimitVolume(calculatedVolume), BB_top, Label, 0, TP_CALC, expiration);
}
}
if (!this.IsBacktesting)
{
ChartObjects.DrawHorizontalLine("BB2 top", BB2_top, Colors.White, 2, LineStyle.Dots);
//BB2 top
ChartObjects.DrawHorizontalLine("BB top", BB_top, Colors.Yellow, 2, LineStyle.Dots);
//BB top
ChartObjects.DrawHorizontalLine("mid", mid, Colors.White, 2, LineStyle.Dots);
//BB mid
ChartObjects.DrawHorizontalLine("BB bottom", BB_bottom, Colors.Yellow, 2, LineStyle.Dots);
//BB bottom
ChartObjects.DrawHorizontalLine("BB2 bottom", BB2_bottom, Colors.White, 2, LineStyle.Dots);
//BB2 bottom
ChartObjects.DrawText("AO", "AO: " + AO, StaticPosition.TopRight, Colors.White);
ChartObjects.DrawText("AO_last", "\n AAO - last: " + AO_last, StaticPosition.TopRight, Colors.White);
//AO REsults
}
}
//------------------------------------------------------------------------------------------------------------
private void ProcessTrades()
{
if (Buy && CountOfTradesOfType(TradeType.Buy) == 0 && MarketSeries.Close.Last(1) > MarketSeries.Close.Last(2))
{
_openTradeResult = OrderSend(TradeType.Buy, LimitVolume(FirstVolume));
if (_openTradeResult > 0)
_lastBuyTradeTime = MarketSeries.OpenTime.Last(0);
else
Print("First BUY openning error at: ", Symbol.Ask, "Error Type: ", LastResult.Error);
}
if (Sell && CountOfTradesOfType(TradeType.Sell) == 0 && MarketSeries.Close.Last(2) > MarketSeries.Close.Last(1))
{
_openTradeResult = OrderSend(TradeType.Sell, LimitVolume(FirstVolume));
if (_openTradeResult > 0)
_lastSellTradeTime = MarketSeries.OpenTime.Last(0);
else
Print("First SELL opening error at: ", Symbol.Bid, "Error Type: ", LastResult.Error);
}
if (CountOfTradesOfType(TradeType.Buy) > 0)
{
if (Math.Round(Symbol.Ask, Symbol.Digits) < Math.Round(FindLowestPositionPrice(TradeType.Buy) - PipStep * Symbol.PipSize, Symbol.Digits) && _lastBuyTradeTime != MarketSeries.OpenTime.Last(0))
{
var calculatedVolume = CalculateVolume(TradeType.Buy);
_openTradeResult = OrderSend(TradeType.Buy, LimitVolume(calculatedVolume));
if (_openTradeResult > 0)
_lastBuyTradeTime = MarketSeries.OpenTime.Last(0);
else
Print("Next BUY opening error at: ", Symbol.Ask, "Error Type: ", LastResult.Error);
}
}
if (CountOfTradesOfType(TradeType.Sell) > 0)
{
if (Math.Round(Symbol.Bid, Symbol.Digits) > Math.Round(FindHighestPositionPrice(TradeType.Sell) + PipStep * Symbol.PipSize, Symbol.Digits) && _lastSellTradeTime != MarketSeries.OpenTime.Last(0))
{
var calculatedVolume = CalculateVolume(TradeType.Sell);
_openTradeResult = OrderSend(TradeType.Sell, LimitVolume(calculatedVolume));
if (_openTradeResult > 0)
_lastSellTradeTime = MarketSeries.OpenTime.Last(0);
else
Print("Next SELL opening error at: ", Symbol.Bid, "Error Type: ", LastResult.Error);
}
}
}
private int OrderSend(TradeType tradeType, long volumeToUse)
{
var returnResult = 0;
if (volumeToUse > 0)
{
var result = ExecuteMarketOrder(tradeType, Symbol, volumeToUse, Label, 0, 0, 0, "smart_grid");
if (result.IsSuccessful)
{
Print(tradeType, "Opened at: ", result.Position.EntryPrice);
returnResult = 1;
}
else
Print(tradeType, "Openning Error: ", result.Error);
}
else
Print("Volume calculation error: Calculated Volume is: ", volumeToUse);
return returnResult;
}
private void AdjustBuyPositionTakeProfits(double averageBuyPositionPrice, int averageTakeProfit)
{
foreach (var buyPosition in Positions)
{
if (buyPosition.Label == Label && buyPosition.SymbolCode == Symbol.Code)
{
if (buyPosition.TradeType == TradeType.Buy)
{
double? calculatedTakeProfit = Math.Round(averageBuyPositionPrice + averageTakeProfit * Symbol.PipSize, Symbol.Digits);
if (buyPosition.TakeProfit != calculatedTakeProfit)
ModifyPosition(buyPosition, buyPosition.StopLoss, calculatedTakeProfit);
}
}
}
}
private void AdjustSellPositionTakeProfits(double averageSellPositionPrice, int averageTakeProfit)
{
foreach (var sellPosition in Positions)
{
if (sellPosition.Label == Label && sellPosition.SymbolCode == Symbol.Code)
{
if (sellPosition.TradeType == TradeType.Sell)
{
double? calculatedTakeProfit = Math.Round(averageSellPositionPrice - averageTakeProfit * Symbol.PipSize, Symbol.Digits);
if (sellPosition.TakeProfit != calculatedTakeProfit)
ModifyPosition(sellPosition, sellPosition.StopLoss, calculatedTakeProfit);
}
}
}
}
private void DisplayStatusOnChart()
{
if (CountOfTradesOfType(TradeType.Buy) > 1)
{
var y = CalculateAveragePositionPrice(TradeType.Buy);
ChartObjects.DrawHorizontalLine("bpoint", y, Colors.Yellow, 2, LineStyle.Dots);
}
else
ChartObjects.RemoveObject("bpoint");
if (CountOfTradesOfType(TradeType.Sell) > 1)
{
var z = CalculateAveragePositionPrice(TradeType.Sell);
ChartObjects.DrawHorizontalLine("spoint", z, Colors.HotPink, 2, LineStyle.Dots);
}
else
ChartObjects.RemoveObject("spoint");
ChartObjects.DrawText("pan", GenerateStatusText(), StaticPosition.TopLeft, Colors.Tomato);
}
private string GenerateStatusText()
{
var statusText = "";
var buyPositions = "";
var sellPositions = "";
var spread = "";
var buyDistance = "";
var sellDistance = "";
spread = "\nSpread = " + Math.Round(CurrentSpread, 1);
buyPositions = "\nBuy Positions = " + CountOfTradesOfType(TradeType.Buy);
sellPositions = "\nSell Positions = " + CountOfTradesOfType(TradeType.Sell);
if (CountOfTradesOfType(TradeType.Buy) > 0)
{
var averageBuyFromCurrent = Math.Round((CalculateAveragePositionPrice(TradeType.Buy) - Symbol.Bid) / Symbol.PipSize, 1);
buyDistance = "\nBuy Target Away = " + averageBuyFromCurrent;
}
if (CountOfTradesOfType(TradeType.Sell) > 0)
{
var averageSellFromCurrent = Math.Round((Symbol.Ask - CalculateAveragePositionPrice(TradeType.Sell)) / Symbol.PipSize, 1);
sellDistance = "\nSell Target Away = " + averageSellFromCurrent;
}
if (CurrentSpread > MaxSpread)
statusText = "MAX SPREAD EXCEED";
else
statusText = "Smart Grid" + buyPositions + spread + sellPositions + buyDistance + sellDistance;
return (statusText);
}
private int CountOfTradesOfType(TradeType tradeType)
{
var tradeCount = 0;
foreach (var position in Positions)
{
if (position.Label == Label && position.SymbolCode == Symbol.Code)
{
if (position.TradeType == tradeType)
tradeCount++;
}
}
return tradeCount;
}
private double CalculateAveragePositionPrice(TradeType tradeType)
{
double result = 0;
double averagePrice = 0;
long count = 0;
foreach (var position in Positions)
{
if (position.Label == Label && position.SymbolCode == Symbol.Code)
{
if (position.TradeType == tradeType)
{
averagePrice += position.EntryPrice * position.Volume;
count += position.Volume;
}
}
}
if (averagePrice > 0 && count > 0)
result = Math.Round(averagePrice / count, Symbol.Digits);
return result;
}
private double FindLowestPositionPrice(TradeType tradeType)
{
double lowestPrice = 0;
foreach (var position in Positions)
{
if (position.Label == Label && position.SymbolCode == Symbol.Code)
{
if (position.TradeType == tradeType)
{
if (lowestPrice == 0)
{
lowestPrice = position.EntryPrice;
continue;
}
if (position.EntryPrice < lowestPrice)
lowestPrice = position.EntryPrice;
}
}
}
return lowestPrice;
}
private double FindHighestPositionPrice(TradeType tradeType)
{
double highestPrice = 0;
foreach (var position in Positions)
{
if (position.Label == Label && position.SymbolCode == Symbol.Code)
{
if (position.TradeType == tradeType)
{
if (highestPrice == 0)
{
highestPrice = position.EntryPrice;
continue;
}
if (position.EntryPrice > highestPrice)
highestPrice = position.EntryPrice;
}
}
}
return highestPrice;
}
private double FindPriceOfMostRecentPositionId(TradeType tradeType)
{
double price = 0;
var highestPositionId = 0;
foreach (var position in Positions)
{
if (position.Label == Label && position.SymbolCode == Symbol.Code)
{
if (position.TradeType == tradeType)
{
if (highestPositionId == 0 || highestPositionId > position.Id)
{
price = position.EntryPrice;
highestPositionId = position.Id;
}
}
}
}
return price;
}
private long GetMostRecentPositionVolume(TradeType tradeType)
{
long mostRecentVolume = 0;
var highestPositionId = 0;
foreach (var position in Positions)
{
if (position.Label == Label && position.SymbolCode == Symbol.Code)
{
if (position.TradeType == tradeType)
{
if (highestPositionId == 0 || highestPositionId > position.Id)
{
mostRecentVolume = position.Volume;
highestPositionId = position.Id;
}
}
}
}
return mostRecentVolume;
}
private int CountNumberOfPositionsOfType(TradeType tradeType)
{
var mostRecentPrice = FindPriceOfMostRecentPositionId(tradeType);
var numberOfPositionsOfType = 0;
foreach (var position in Positions)
{
if (position.Label == Label && position.SymbolCode == Symbol.Code)
{
if (position.TradeType == tradeType && tradeType == TradeType.Buy)
{
if (Math.Round(position.EntryPrice, Symbol.Digits) <= Math.Round(mostRecentPrice, Symbol.Digits))
numberOfPositionsOfType++;
}
if (position.TradeType == tradeType && tradeType == TradeType.Sell)
{
if (Math.Round(position.EntryPrice, Symbol.Digits) >= Math.Round(mostRecentPrice, Symbol.Digits))
numberOfPositionsOfType++;
}
}
}
return (numberOfPositionsOfType);
}
private long CalculateVolume(TradeType tradeType)
{
var numberOfPositions = CountNumberOfPositionsOfType(tradeType);
var mostRecentVolume = GetMostRecentPositionVolume(tradeType);
var calculatedVolume = Symbol.NormalizeVolume(mostRecentVolume * Math.Pow(VolumeExponent, numberOfPositions));
return (calculatedVolume);
}
private long LimitVolume(long volumeIn)
{
var symbolVolumeMin = Symbol.VolumeMin;
var symbolVolumeMax = Symbol.VolumeMax;
var result = volumeIn;
if (result < symbolVolumeMin)
result = symbolVolumeMin;
if (result > symbolVolumeMax)
result = symbolVolumeMax;
return (result);
}
// - tweaks
private void indicators()
{
var AO = Math.Round(awesomeOscillator.Result.Last(0), 5);
var AO_last = Math.Round(awesomeOscillator.Result.Last(1), 5);
ChartObjects.DrawHorizontalLine("BB2 top", BB_2boll.Top.LastValue, Colors.White, 2, LineStyle.Dots);
//BB2 top
ChartObjects.DrawHorizontalLine("BB top", BB_boll.Top.LastValue, Colors.Yellow, 2, LineStyle.Dots);
//BB top
ChartObjects.DrawHorizontalLine("mid", BB_boll.Main.LastValue, Colors.White, 2, LineStyle.Dots);
//BB mid
ChartObjects.DrawHorizontalLine("BB bottom", BB_boll.Bottom.LastValue, Colors.Yellow, 2, LineStyle.Dots);
//BB bottom
ChartObjects.DrawHorizontalLine("BB2 bottom", BB_2boll.Bottom.LastValue, Colors.White, 2, LineStyle.Dots);
//BB2 bottom
ChartObjects.DrawText("AO", "AO: " + AO, StaticPosition.TopRight, Colors.White);
ChartObjects.DrawText("AO_last", "\n AAO - last: " + AO_last, StaticPosition.TopRight, Colors.White);
//AO REsults
}
}
}
@jumpycalm working on something new right now!
been away for a while! sure, we can develop something together!
@jumpycalm thank you very much!
Been away for a While, how is it going? if you want, we can work together in future devs!
Best regards
Bruno Candeias
Here it goes, debugged and updated
//
//+------------------------------------------------------------------+
//| Smart Grid |
//| Copyright 2014, MD SAIF |
//| http://www.facebook.com/cls.fx |
//+------------------------------------------------------------------+
//-Grid trader cBot based on Bar-Time & Trend. For range market & 15 minute TimeFrame is best.
using System;
using cAlgo.API;
namespace cAlgo
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class SmartGrid : Robot
{
private bool _accountIsOutOfMoney;
private int _openTradeResult;
private readonly string Label = "SmartGrid2";
private DateTime _lastBuyTradeTime;
private DateTime _lastSellTradeTime;
[Parameter("Buy", DefaultValue = true)]
public bool Buy { get; set; }
[Parameter("Sell", DefaultValue = true)]
public bool Sell { get; set; }
[Parameter("Pip Step", DefaultValue = 10, MinValue = 1)]
public int PipStep { get; set; }
[Parameter("First Volume", DefaultValue = 1000, MinValue = 1000, Step = 1000)]
public int FirstVolume { get; set; }
[Parameter("Volume Exponent", DefaultValue = 1.0, MinValue = 0.1, MaxValue = 5.0)]
public double VolumeExponent { get; set; }
[Parameter("Max Spread", DefaultValue = 3.0)]
public double MaxSpread { get; set; }
[Parameter("Average TP", DefaultValue = 3, MinValue = 1)]
public int AverageTakeProfit { get; set; }
private double CurrentSpread
{
get { return (Symbol.Ask - Symbol.Bid) / Symbol.PipSize; }
}
protected override void OnStart()
{
}
protected override void OnTick()
{
if (CountOfTradesOfType(TradeType.Buy) > 0)
AdjustBuyPositionTakeProfits(CalculateAveragePositionPrice(TradeType.Buy), AverageTakeProfit);
if (CountOfTradesOfType(TradeType.Sell) > 0)
AdjustSellPositionTakeProfits(CalculateAveragePositionPrice(TradeType.Sell), AverageTakeProfit);
if (CurrentSpread <= MaxSpread && !_accountIsOutOfMoney)
ProcessTrades();
if (!this.IsBacktesting)
DisplayStatusOnChart();
}
protected override void OnError(Error error)
{
if (error.Code == ErrorCode.NoMoney)
{
_accountIsOutOfMoney = true;
Print("opening stopped because: not enough money");
}
}
protected override void OnBar()
{
RefreshData();
}
protected override void OnStop()
{
// ChartObjects.RemoveAllObjects();
Chart.RemoveAllObjects();
}
private void ProcessTrades()
{
if (Buy && CountOfTradesOfType(TradeType.Buy) == 0 && MarketSeries.Close.Last(1) > MarketSeries.Close.Last(2))
{
_openTradeResult = OrderSend(TradeType.Buy, LimitVolume(FirstVolume));
if (_openTradeResult > 0)
_lastBuyTradeTime = MarketSeries.OpenTime.Last(0);
else
Print("First BUY openning error at: ", Symbol.Ask, "Error Type: ", LastResult.Error);
}
if (Sell && CountOfTradesOfType(TradeType.Sell) == 0 && MarketSeries.Close.Last(2) > MarketSeries.Close.Last(1))
{
_openTradeResult = OrderSend(TradeType.Sell, LimitVolume(FirstVolume));
if (_openTradeResult > 0)
_lastSellTradeTime = MarketSeries.OpenTime.Last(0);
else
Print("First SELL opening error at: ", Symbol.Bid, "Error Type: ", LastResult.Error);
}
if (CountOfTradesOfType(TradeType.Buy) > 0)
{
if (Math.Round(Symbol.Ask, Symbol.Digits) < Math.Round(FindLowestPositionPrice(TradeType.Buy) - PipStep * Symbol.PipSize, Symbol.Digits) && _lastBuyTradeTime != MarketSeries.OpenTime.Last(0))
{
var calculatedVolume = CalculateVolume(TradeType.Buy);
_openTradeResult = OrderSend(TradeType.Buy, LimitVolume(calculatedVolume));
if (_openTradeResult > 0)
_lastBuyTradeTime = MarketSeries.OpenTime.Last(0);
else
Print("Next BUY opening error at: ", Symbol.Ask, "Error Type: ", LastResult.Error);
}
}
if (CountOfTradesOfType(TradeType.Sell) > 0)
{
if (Math.Round(Symbol.Bid, Symbol.Digits) > Math.Round(FindHighestPositionPrice(TradeType.Sell) + PipStep * Symbol.PipSize, Symbol.Digits) && _lastSellTradeTime != MarketSeries.OpenTime.Last(0))
{
var calculatedVolume = CalculateVolume(TradeType.Sell);
_openTradeResult = OrderSend(TradeType.Sell, LimitVolume(calculatedVolume));
if (_openTradeResult > 0)
_lastSellTradeTime = MarketSeries.OpenTime.Last(0);
else
Print("Next SELL opening error at: ", Symbol.Bid, "Error Type: ", LastResult.Error);
}
}
}
private int OrderSend(TradeType tradeType, double volumeToUse)
{
var returnResult = 0;
if (volumeToUse > 0)
{
var result = ExecuteMarketOrder(tradeType, Symbol, volumeToUse, Label, 0, 0, 0, "smart_grid");
if (result.IsSuccessful)
{
Print(tradeType, "Opened at: ", result.Position.EntryPrice);
returnResult = 1;
}
else
Print(tradeType, "Openning Error: ", result.Error);
}
else
Print("Volume calculation error: Calculated Volume is: ", volumeToUse);
return returnResult;
}
private void AdjustBuyPositionTakeProfits(double averageBuyPositionPrice, int averageTakeProfit)
{
foreach (var buyPosition in Positions)
{
if (buyPosition.Label == Label && buyPosition.SymbolCode == Symbol.Code)
{
if (buyPosition.TradeType == TradeType.Buy)
{
double? calculatedTakeProfit = Math.Round(averageBuyPositionPrice + averageTakeProfit * Symbol.PipSize, Symbol.Digits);
if (buyPosition.TakeProfit != calculatedTakeProfit)
ModifyPosition(buyPosition, buyPosition.StopLoss, calculatedTakeProfit);
}
}
}
}
private void AdjustSellPositionTakeProfits(double averageSellPositionPrice, int averageTakeProfit)
{
foreach (var sellPosition in Positions)
{
if (sellPosition.Label == Label && sellPosition.SymbolCode == Symbol.Code)
{
if (sellPosition.TradeType == TradeType.Sell)
{
double? calculatedTakeProfit = Math.Round(averageSellPositionPrice - averageTakeProfit * Symbol.PipSize, Symbol.Digits);
if (sellPosition.TakeProfit != calculatedTakeProfit)
ModifyPosition(sellPosition, sellPosition.StopLoss, calculatedTakeProfit);
}
}
}
}
private void DisplayStatusOnChart()
{
if (CountOfTradesOfType(TradeType.Buy) > 1)
{
var y = CalculateAveragePositionPrice(TradeType.Buy);
// ChartObjects.DrawHorizontalLine("bpoint", y, Colors.Yellow, 2, LineStyle.Dots);
Chart.DrawHorizontalLine("bpoint", y, Color.Yellow, 2, LineStyle.Dots);
}
else
//ChartObjects.RemoveObject("bpoint");
Chart.RemoveObject("bpoint");
if (CountOfTradesOfType(TradeType.Sell) > 1)
{
var z = CalculateAveragePositionPrice(TradeType.Sell);
//ChartObjects.DrawHorizontalLine("spoint", z, Colors.HotPink, 2, LineStyle.Dots);
Chart.DrawHorizontalLine("spoint", z, Color.HotPink, 2, LineStyle.Dots);
}
else
//ChartObjects.RemoveObject("spoint");
Chart.RemoveObject("spoint");
//ChartObjects.DrawText("pan", GenerateStatusText(), StaticPosition.TopLeft, Colors.Tomato);
Chart.DrawStaticText("pan", GenerateStatusText(), VerticalAlignment.Top, HorizontalAlignment.Left, Color.Tomato);
}
private string GenerateStatusText()
{
var statusText = "";
var buyPositions = "";
var sellPositions = "";
var spread = "";
var buyDistance = "";
var sellDistance = "";
spread = "\nSpread = " + Math.Round(CurrentSpread, 1);
buyPositions = "\nBuy Positions = " + CountOfTradesOfType(TradeType.Buy);
sellPositions = "\nSell Positions = " + CountOfTradesOfType(TradeType.Sell);
if (CountOfTradesOfType(TradeType.Buy) > 0)
{
var averageBuyFromCurrent = Math.Round((CalculateAveragePositionPrice(TradeType.Buy) - Symbol.Bid) / Symbol.PipSize, 1);
buyDistance = "\nBuy Target Away = " + averageBuyFromCurrent;
}
if (CountOfTradesOfType(TradeType.Sell) > 0)
{
var averageSellFromCurrent = Math.Round((Symbol.Ask - CalculateAveragePositionPrice(TradeType.Sell)) / Symbol.PipSize, 1);
sellDistance = "\nSell Target Away = " + averageSellFromCurrent;
}
if (CurrentSpread > MaxSpread)
statusText = "MAX SPREAD EXCEED";
else
statusText = "Smart Grid" + buyPositions + spread + sellPositions + buyDistance + sellDistance;
return (statusText);
}
private int CountOfTradesOfType(TradeType tradeType)
{
var tradeCount = 0;
foreach (var position in Positions)
{
if (position.Label == Label && position.SymbolCode == Symbol.Code)
{
if (position.TradeType == tradeType)
tradeCount++;
}
}
return tradeCount;
}
private double CalculateAveragePositionPrice(TradeType tradeType)
{
double result = 0;
double averagePrice = 0;
double count = 0;
foreach (var position in Positions)
{
if (position.Label == Label && position.SymbolCode == Symbol.Code)
{
if (position.TradeType == tradeType)
{
averagePrice += position.EntryPrice * position.VolumeInUnits;
count += position.VolumeInUnits;
}
}
}
if (averagePrice > 0 && count > 0)
result = Math.Round(averagePrice / count, Symbol.Digits);
return result;
}
private double FindLowestPositionPrice(TradeType tradeType)
{
double lowestPrice = 0;
foreach (var position in Positions)
{
if (position.Label == Label && position.SymbolCode == Symbol.Code)
{
if (position.TradeType == tradeType)
{
if (lowestPrice == 0)
{
lowestPrice = position.EntryPrice;
continue;
}
if (position.EntryPrice < lowestPrice)
lowestPrice = position.EntryPrice;
}
}
}
return lowestPrice;
}
private double FindHighestPositionPrice(TradeType tradeType)
{
double highestPrice = 0;
foreach (var position in Positions)
{
if (position.Label == Label && position.SymbolCode == Symbol.Code)
{
if (position.TradeType == tradeType)
{
if (highestPrice == 0)
{
highestPrice = position.EntryPrice;
continue;
}
if (position.EntryPrice > highestPrice)
highestPrice = position.EntryPrice;
}
}
}
return highestPrice;
}
private double FindPriceOfMostRecentPositionId(TradeType tradeType)
{
double price = 0;
var highestPositionId = 0;
foreach (var position in Positions)
{
if (position.Label == Label && position.SymbolCode == Symbol.Code)
{
if (position.TradeType == tradeType)
{
if (highestPositionId == 0 || highestPositionId > position.Id)
{
price = position.EntryPrice;
highestPositionId = position.Id;
}
}
}
}
return price;
}
private double GetMostRecentPositionVolume(TradeType tradeType)
{
double mostRecentVolume = 0;
var highestPositionId = 0;
foreach (var position in Positions)
{
if (position.Label == Label && position.SymbolCode == Symbol.Code)
{
if (position.TradeType == tradeType)
{
if (highestPositionId == 0 || highestPositionId > position.Id)
{
mostRecentVolume = position.VolumeInUnits;
highestPositionId = position.Id;
}
}
}
}
return mostRecentVolume;
}
private int CountNumberOfPositionsOfType(TradeType tradeType)
{
var mostRecentPrice = FindPriceOfMostRecentPositionId(tradeType);
var numberOfPositionsOfType = 0;
foreach (var position in Positions)
{
if (position.Label == Label && position.SymbolCode == Symbol.Code)
{
if (position.TradeType == tradeType && tradeType == TradeType.Buy)
{
if (Math.Round(position.EntryPrice, Symbol.Digits) <= Math.Round(mostRecentPrice, Symbol.Digits))
numberOfPositionsOfType++;
}
if (position.TradeType == tradeType && tradeType == TradeType.Sell)
{
if (Math.Round(position.EntryPrice, Symbol.Digits) >= Math.Round(mostRecentPrice, Symbol.Digits))
numberOfPositionsOfType++;
}
}
}
return (numberOfPositionsOfType);
}
private double CalculateVolume(TradeType tradeType)
{
var numberOfPositions = CountNumberOfPositionsOfType(tradeType);
var mostRecentVolume = GetMostRecentPositionVolume(tradeType);
var calculatedVolume = Symbol.NormalizeVolumeInUnits(mostRecentVolume * Math.Pow(VolumeExponent, numberOfPositions));
return (calculatedVolume);
}
private double LimitVolume(double volumeIn)
{
var symbolVolumeMin = Symbol.VolumeInUnitsMin;
var symbolVolumeMax = Symbol.VolumeInUnitsMax;
var result = volumeIn;
if (result < symbolVolumeMin)
result = symbolVolumeMin;
if (result > symbolVolumeMax)
result = symbolVolumeMax;
return (result);
}
}
}
@[amantalpur007@gmail.com] here you go:
//+------------------------------------------------------------------+
//| Smart Grid |
//| Copyright 2014, MD SAIF |
//| http://www.facebook.com/cls.fx |
//+------------------------------------------------------------------+
//-Grid trader cBot based on Bar-Time & Trend. For range market & 15 minute TimeFrame is best.
using System;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
namespace cAlgo
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class SmartGrid : Robot
{
private bool _accountIsOutOfMoney;
private int _openTradeResult;
private readonly string Label = "SmartGrid2";
private DateTime _lastBuyTradeTime;
private DateTime _lastSellTradeTime;
[Parameter("Source SMA_AO")]
public DataSeries Source_SMA { get; set; }
[Parameter("Buy", DefaultValue = true)]
public bool Buy { get; set; }
[Parameter("Sell", DefaultValue = true)]
public bool Sell { get; set; }
[Parameter("Pip Step", DefaultValue = 10, MinValue = 1)]
public int PipStep { get; set; }
[Parameter("First Volume", DefaultValue = 1000, MinValue = 1000, Step = 1000)]
public int FirstVolume { get; set; }
[Parameter("Volume Exponent", DefaultValue = 1.0, MinValue = 0.1, MaxValue = 5.0)]
public double VolumeExponent { get; set; }
[Parameter("Max Spread", DefaultValue = 3.0)]
public double MaxSpread { get; set; }
[Parameter("Average TP", DefaultValue = 3, MinValue = 1)]
public int AverageTakeProfit { get; set; }
[Parameter("Stop Loss", DefaultValue = 10)]
public int StopLoss { get; set; }
private double CurrentSpread
{
get { return (Symbol.Ask - Symbol.Bid) / Symbol.PipSize; }
}
private SimpleMovingAverage _SMA_slow;
private SimpleMovingAverage _SMA_Fast;
protected override void OnStart()
{
}
protected override void OnTick()
{
_SMA_slow = Indicators.SimpleMovingAverage(Source_SMA, 200);
_SMA_Fast = Indicators.SimpleMovingAverage(Source_SMA, 50);
if (_SMA_slow.Result.LastValue > _SMA_Fast.Result.LastValue && _SMA_slow.Result.LastValue > Symbol.Bid)
{
Buy = false;
Sell = true;
ChartObjects.DrawText("Sell", ("Vender"), StaticPosition.TopLeft, Colors.AliceBlue);
}
if (_SMA_slow.Result.LastValue < _SMA_Fast.Result.LastValue && _SMA_slow.Result.LastValue < Symbol.Ask)
{
Buy = true;
Sell = false;
ChartObjects.DrawText("buy", ("Comprar"), StaticPosition.TopLeft, Colors.AliceBlue);
}
if (CountOfTradesOfType(TradeType.Buy) > 0)
AdjustBuyPositionTakeProfits(CalculateAveragePositionPrice(TradeType.Buy), AverageTakeProfit);
if (CountOfTradesOfType(TradeType.Sell) > 0)
AdjustSellPositionTakeProfits(CalculateAveragePositionPrice(TradeType.Sell), AverageTakeProfit);
if (CurrentSpread <= MaxSpread && !_accountIsOutOfMoney)
ProcessTrades();
if (!this.IsBacktesting)
DisplayStatusOnChart();
}
protected override void OnError(Error error)
{
if (error.Code == ErrorCode.NoMoney)
{
_accountIsOutOfMoney = true;
Print("opening stopped because: not enough money");
}
}
protected override void OnBar()
{
RefreshData();
}
protected override void OnStop()
{
ChartObjects.RemoveAllObjects();
}
private void ProcessTrades()
{
if (Buy && CountOfTradesOfType(TradeType.Buy) == 0 && MarketSeries.Close.Last(1) > MarketSeries.Close.Last(2))
{
_openTradeResult = OrderSend(TradeType.Buy, LimitVolume(FirstVolume));
if (_openTradeResult > 0)
_lastBuyTradeTime = MarketSeries.OpenTime.Last(0);
else
Print("First BUY openning error at: ", Symbol.Ask, "Error Type: ", LastResult.Error);
}
if (Sell && CountOfTradesOfType(TradeType.Sell) == 0 && MarketSeries.Close.Last(2) > MarketSeries.Close.Last(1))
{
_openTradeResult = OrderSend(TradeType.Sell, LimitVolume(FirstVolume));
if (_openTradeResult > 0)
_lastSellTradeTime = MarketSeries.OpenTime.Last(0);
else
Print("First SELL opening error at: ", Symbol.Bid, "Error Type: ", LastResult.Error);
}
if (CountOfTradesOfType(TradeType.Buy) > 0)
{
if (Math.Round(Symbol.Ask, Symbol.Digits) < Math.Round(FindLowestPositionPrice(TradeType.Buy) - PipStep * Symbol.PipSize, Symbol.Digits) && _lastBuyTradeTime != MarketSeries.OpenTime.Last(0))
{
var calculatedVolume = CalculateVolume(TradeType.Buy);
_openTradeResult = OrderSend(TradeType.Buy, LimitVolume(calculatedVolume));
if (_openTradeResult > 0)
_lastBuyTradeTime = MarketSeries.OpenTime.Last(0);
else
Print("Next BUY opening error at: ", Symbol.Ask, "Error Type: ", LastResult.Error);
}
}
if (CountOfTradesOfType(TradeType.Sell) > 0)
{
if (Math.Round(Symbol.Bid, Symbol.Digits) > Math.Round(FindHighestPositionPrice(TradeType.Sell) + PipStep * Symbol.PipSize, Symbol.Digits) && _lastSellTradeTime != MarketSeries.OpenTime.Last(0))
{
var calculatedVolume = CalculateVolume(TradeType.Sell);
_openTradeResult = OrderSend(TradeType.Sell, LimitVolume(calculatedVolume));
if (_openTradeResult > 0)
_lastSellTradeTime = MarketSeries.OpenTime.Last(0);
else
Print("Next SELL opening error at: ", Symbol.Bid, "Error Type: ", LastResult.Error);
}
}
}
private int OrderSend(TradeType tradeType, long volumeToUse)
{
var returnResult = 0;
if (volumeToUse > 0)
{
var result = ExecuteMarketOrder(tradeType, Symbol, volumeToUse, Label, StopLoss, 0, 0, "smart_grid");
if (result.IsSuccessful)
{
Print(tradeType, "Opened at: ", result.Position.EntryPrice, result.Position.StopLoss);
returnResult = 1;
}
else
Print(tradeType, "Openning Error: ", result.Error);
}
else
Print("Volume calculation error: Calculated Volume is: ", volumeToUse);
return returnResult;
}
private void AdjustBuyPositionTakeProfits(double averageBuyPositionPrice, int averageTakeProfit)
{
foreach (var buyPosition in Positions)
{
if (buyPosition.Label == Label && buyPosition.SymbolCode == Symbol.Code)
{
if (buyPosition.TradeType == TradeType.Buy)
{
double? calculatedTakeProfit = Math.Round(averageBuyPositionPrice + averageTakeProfit * Symbol.PipSize, Symbol.Digits);
if (buyPosition.TakeProfit != calculatedTakeProfit)
ModifyPosition(buyPosition, buyPosition.StopLoss, calculatedTakeProfit);
}
}
}
}
private void AdjustSellPositionTakeProfits(double averageSellPositionPrice, int averageTakeProfit)
{
foreach (var sellPosition in Positions)
{
if (sellPosition.Label == Label && sellPosition.SymbolCode == Symbol.Code)
{
if (sellPosition.TradeType == TradeType.Sell)
{
double? calculatedTakeProfit = Math.Round(averageSellPositionPrice - averageTakeProfit * Symbol.PipSize, Symbol.Digits);
if (sellPosition.TakeProfit != calculatedTakeProfit)
ModifyPosition(sellPosition, sellPosition.StopLoss, calculatedTakeProfit);
}
}
}
}
private void DisplayStatusOnChart()
{
if (CountOfTradesOfType(TradeType.Buy) > 1)
{
var y = CalculateAveragePositionPrice(TradeType.Buy);
ChartObjects.DrawHorizontalLine("bpoint", y, Colors.Yellow, 2, LineStyle.Dots);
}
else
ChartObjects.RemoveObject("bpoint");
if (CountOfTradesOfType(TradeType.Sell) > 1)
{
var z = CalculateAveragePositionPrice(TradeType.Sell);
ChartObjects.DrawHorizontalLine("spoint", z, Colors.HotPink, 2, LineStyle.Dots);
}
else
ChartObjects.RemoveObject("spoint");
ChartObjects.DrawText("pan", GenerateStatusText(), StaticPosition.TopLeft, Colors.Tomato);
}
private string GenerateStatusText()
{
var statusText = "";
var buyPositions = "";
var sellPositions = "";
var spread = "";
var buyDistance = "";
var sellDistance = "";
spread = "\nSpread = " + Math.Round(CurrentSpread, 1);
buyPositions = "\nBuy Positions = " + CountOfTradesOfType(TradeType.Buy);
sellPositions = "\nSell Positions = " + CountOfTradesOfType(TradeType.Sell);
if (CountOfTradesOfType(TradeType.Buy) > 0)
{
var averageBuyFromCurrent = Math.Round((CalculateAveragePositionPrice(TradeType.Buy) - Symbol.Bid) / Symbol.PipSize, 1);
buyDistance = "\nBuy Target Away = " + averageBuyFromCurrent;
}
if (CountOfTradesOfType(TradeType.Sell) > 0)
{
var averageSellFromCurrent = Math.Round((Symbol.Ask - CalculateAveragePositionPrice(TradeType.Sell)) / Symbol.PipSize, 1);
sellDistance = "\nSell Target Away = " + averageSellFromCurrent;
}
if (CurrentSpread > MaxSpread)
statusText = "MAX SPREAD EXCEED";
else
statusText = "Smart Grid" + buyPositions + spread + sellPositions + buyDistance + sellDistance;
return (statusText);
}
private int CountOfTradesOfType(TradeType tradeType)
{
var tradeCount = 0;
foreach (var position in Positions)
{
if (position.Label == Label && position.SymbolCode == Symbol.Code)
{
if (position.TradeType == tradeType)
tradeCount++;
}
}
return tradeCount;
}
private double CalculateAveragePositionPrice(TradeType tradeType)
{
double result = 0;
double averagePrice = 0;
long count = 0;
foreach (var position in Positions)
{
if (position.Label == Label && position.SymbolCode == Symbol.Code)
{
if (position.TradeType == tradeType)
{
averagePrice += position.EntryPrice * position.Volume;
count += position.Volume;
}
}
}
if (averagePrice > 0 && count > 0)
result = Math.Round(averagePrice / count, Symbol.Digits);
return result;
}
private double FindLowestPositionPrice(TradeType tradeType)
{
double lowestPrice = 0;
foreach (var position in Positions)
{
if (position.Label == Label && position.SymbolCode == Symbol.Code)
{
if (position.TradeType == tradeType)
{
if (lowestPrice == 0)
{
lowestPrice = position.EntryPrice;
continue;
}
if (position.EntryPrice < lowestPrice)
lowestPrice = position.EntryPrice;
}
}
}
return lowestPrice;
}
private double FindHighestPositionPrice(TradeType tradeType)
{
double highestPrice = 0;
foreach (var position in Positions)
{
if (position.Label == Label && position.SymbolCode == Symbol.Code)
{
if (position.TradeType == tradeType)
{
if (highestPrice == 0)
{
highestPrice = position.EntryPrice;
continue;
}
if (position.EntryPrice > highestPrice)
highestPrice = position.EntryPrice;
}
}
}
return highestPrice;
}
private double FindPriceOfMostRecentPositionId(TradeType tradeType)
{
double price = 0;
var highestPositionId = 0;
foreach (var position in Positions)
{
if (position.Label == Label && position.SymbolCode == Symbol.Code)
{
if (position.TradeType == tradeType)
{
if (highestPositionId == 0 || highestPositionId > position.Id)
{
price = position.EntryPrice;
highestPositionId = position.Id;
}
}
}
}
return price;
}
private long GetMostRecentPositionVolume(TradeType tradeType)
{
long mostRecentVolume = 0;
var highestPositionId = 0;
foreach (var position in Positions)
{
if (position.Label == Label && position.SymbolCode == Symbol.Code)
{
if (position.TradeType == tradeType)
{
if (highestPositionId == 0 || highestPositionId > position.Id)
{
mostRecentVolume = position.Volume;
highestPositionId = position.Id;
}
}
}
}
return mostRecentVolume;
}
private int CountNumberOfPositionsOfType(TradeType tradeType)
{
var mostRecentPrice = FindPriceOfMostRecentPositionId(tradeType);
var numberOfPositionsOfType = 0;
foreach (var position in Positions)
{
if (position.Label == Label && position.SymbolCode == Symbol.Code)
{
if (position.TradeType == tradeType && tradeType == TradeType.Buy)
{
if (Math.Round(position.EntryPrice, Symbol.Digits) <= Math.Round(mostRecentPrice, Symbol.Digits))
numberOfPositionsOfType++;
}
if (position.TradeType == tradeType && tradeType == TradeType.Sell)
{
if (Math.Round(position.EntryPrice, Symbol.Digits) >= Math.Round(mostRecentPrice, Symbol.Digits))
numberOfPositionsOfType++;
}
}
}
return (numberOfPositionsOfType);
}
private long CalculateVolume(TradeType tradeType)
{
var numberOfPositions = CountNumberOfPositionsOfType(tradeType);
var mostRecentVolume = GetMostRecentPositionVolume(tradeType);
var calculatedVolume = Symbol.NormalizeVolume(mostRecentVolume * Math.Pow(VolumeExponent, numberOfPositions));
return (calculatedVolume);
}
private long LimitVolume(long volumeIn)
{
var symbolVolumeMin = Symbol.VolumeMin;
var symbolVolumeMax = Symbol.VolumeMax;
var result = volumeIn;
if (result < symbolVolumeMin)
result = symbolVolumeMin;
if (result > symbolVolumeMax)
result = symbolVolumeMax;
return (result);
}
}
}
Added this to define direction of trades using SMA crossing:
protected override void OnTick()
{
_SMA_slow = Indicators.SimpleMovingAverage(Source_SMA, 200);
_SMA_Fast = Indicators.SimpleMovingAverage(Source_SMA, 50);
if (_SMA_slow.Result.LastValue > _SMA_Fast.Result.LastValue && _SMA_slow.Result.LastValue > Symbol.Bid)
{
Buy = false;
Sell = true;
// ChartObjects.DrawText("Sell", ("Vender"), StaticPosition.TopLeft, Colors.AliceBlue);
}
if (_SMA_slow.Result.LastValue < _SMA_Fast.Result.LastValue && _SMA_slow.Result.LastValue < Symbol.Ask)
{
Buy = true;
Sell = false;
// ChartObjects.DrawText("buy", ("Comprar"), StaticPosition.TopLeft, Colors.AliceBlue);
}
Thank you! :)