Topics
Forum Topics not found
Replies
amusleh
11 Apr 2022, 14:32
Hi,
The Open API returns the last closed bar data if you pass right parameters to trend bar request.
To get only the last closed bar set the to timestamp to now and request count field to 1, then it will return only the last bar data.
If you are using our Open API Python package (OpenApiPy) there was an issue on it's samples related to Python date time to Unix time conversion, we fixed it, please update your samples.
@amusleh
amusleh
11 Apr 2022, 13:32
( Updated at: 11 Apr 2022, 13:33 )
Hi,
Version 4.2 is in beta test, we don't have any exact release date for it yet.
We are testing and collecting bug reports from users right now for 4.2.
If your indicator code is visible in 4.1 and not visible on 4.2 code editor, then please send us via email the indicator ",algo" file with it's solution directory which is inside cAlgo/sources/Indicators folder.
Our email: connect@spotware.com
@amusleh
amusleh
11 Apr 2022, 13:29
( Updated at: 11 Apr 2022, 14:35 )
Hi,
The max lots per split can't be greater than lots as lots is the total volume you want to split in smaller parts, max lots if the maximum allowed value for a split of lots.
And during testing I found some issues on my code, please use this updated version:
using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class IcebergDemo : Robot
{
[Parameter("Label", DefaultValue = "_")]
public string _name { get; set; }
[Parameter("Maximum Visible Lots", Group = "Iceberg Settings", DefaultValue = 1, MaxValue = 100, MinValue = 1, Step = 1)]
public double _maxvisiblelots { get; set; }
[Parameter("Total Lots Needed", Group = "Risk", DefaultValue = 1.0, MaxValue = 100.0, MinValue = 0.01, Step = 0.01)]
public double _total_lots_needed { get; set; }
[Parameter("Stop Loss", Group = "Risk", DefaultValue = 10, MaxValue = 10000, MinValue = 0.1, Step = 0.1)]
public double _stoploss { get; set; }
[Parameter("Take Profit", Group = "Risk", DefaultValue = 15, MaxValue = 10000, MinValue = 0.1, Step = 0.1)]
public double _takeprofit { get; set; }
private bool _buy, _sell;
private MovingAverage _fast;
private MovingAverage _slow;
protected override void OnStart()
{
_fast = Indicators.MovingAverage(Bars.ClosePrices, 12, MovingAverageType.Exponential);
_slow = Indicators.MovingAverage(Bars.ClosePrices, 26, MovingAverageType.Exponential);
}
protected override void OnBar()
{
var ActiveBuy = Positions.Find(_name, Symbol.Name, TradeType.Buy);
var ActiveSell = Positions.Find(_name, Symbol.Name, TradeType.Sell);
_buy = _fast.Result.HasCrossedAbove(_slow.Result.Last(1), 1);
_sell = _fast.Result.HasCrossedBelow(_slow.Result.Last(1), 1);
double[] volumes = GetVolumeSplits(_total_lots_needed, _maxvisiblelots);
if (volumes.Sum() != Symbol.QuantityToVolumeInUnits(_total_lots_needed))
{
throw new InvalidOperationException(string.Format("Volumes doesn't match, lots sum: {0} | lots to Split: {1} | max split size: {2} | # of splits: {3}", Symbol.VolumeInUnitsToQuantity(volumes.Sum()), _total_lots_needed, _maxvisiblelots, volumes.Length));
}
if (_buy && ActiveBuy == null)
{
for (var i = 0; i < volumes.Length; i++)
{
ExecuteMarketOrder(TradeType.Buy, SymbolName, volumes[i], _name, _stoploss, _takeprofit, History.Count.ToString());
}
}
if (_sell && ActiveSell == null)
{
for (var i = 0; i < volumes.Length; i++)
{
ExecuteMarketOrder(TradeType.Sell, SymbolName, volumes[i], _name, _stoploss, _takeprofit, History.Count.ToString());
}
}
}
private double[] GetVolumeSplits(double lots, double maxLotsPerSplit)
{
if (maxLotsPerSplit > lots) throw new InvalidOperationException("maxLotsPerSplit can't be greater than lots");
var modulus = lots % maxLotsPerSplit;
var numberOfFragments = Convert.ToInt32((lots - modulus) / maxLotsPerSplit);
if (modulus > 0) numberOfFragments++;
var lotsPerFragement = lots / numberOfFragments;
var unitsPerFragment = Symbol.QuantityToVolumeInUnits(lotsPerFragement);
var unitsPerFragementNormalized = Symbol.NormalizeVolumeInUnits(unitsPerFragment, RoundingMode.Up);
var volumes = new double[numberOfFragments];
for (var i = 0; i < numberOfFragments; i++)
{
volumes[i] = i == volumes.Length - 1 && modulus > 0 ? unitsPerFragment - ((unitsPerFragementNormalized - unitsPerFragment) * (volumes.Length - 1)) : unitsPerFragementNormalized;
}
return volumes;
}
}
}
I tested with 3.75 and 3.5 lots and 1 for max lots per split and it worked fine.
I modified your code, the method itself does all the calculation, you don't have to repeat it on your calculate method, just use the method output for your orders.
Also I used History.Count for order comments, to link splits in history for checking.
@amusleh
amusleh
11 Apr 2022, 12:33
Hi,
We are aware of this issue and it's fixed on cTrader 4.2.
But it works if you use ticks inside cBot itself.
Here is an example:
using cAlgo.API;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class NewcBot : Robot
{
private Ticks _ticks;
protected override void OnStart()
{
// Getting a symbol ticks data
_ticks = MarketData.GetTicks(SymbolName);
// Subscribing to upcoming ticks
_ticks.Tick += Ticks_Tick;
}
private void Ticks_Tick(TicksTickEventArgs obj)
{
// Printing Last tick inside Ticks collection
Print("Bid: {0} | Ask: {1} | Time: {2:dd/MM/yyyy HH:mm:ss}", obj.Ticks.LastTick.Bid, obj.Ticks.LastTick.Ask, obj.Ticks.LastTick.Time);
}
}
}
Result:
11/04/2022 09:24:02.489 | Reloaded
11/04/2022 09:23:57.208 | Reloaded
11/04/2022 09:23:53.693 | Reloaded
29/03/2022 23:05:20.667 | Backtesting was stopped
29/03/2022 23:05:20.667 | Bid: 1.10928 | Ask: 1.10928 | Time: 29/03/2022 23:05:20
29/03/2022 23:05:20.412 | Bid: 1.10928 | Ask: 1.1093 | Time: 29/03/2022 23:05:20
29/03/2022 23:05:18.068 | Bid: 1.10929 | Ask: 1.1093 | Time: 29/03/2022 23:05:18
29/03/2022 23:05:14.467 | Bid: 1.10929 | Ask: 1.10931 | Time: 29/03/2022 23:05:14
29/03/2022 23:05:14.263 | Bid: 1.10929 | Ask: 1.1093 | Time: 29/03/2022 23:05:14
29/03/2022 23:05:10.745 | Bid: 1.10927 | Ask: 1.10929 | Time: 29/03/2022 23:05:10
29/03/2022 23:05:10.503 | Bid: 1.10926 | Ask: 1.10929 | Time: 29/03/2022 23:05:10
29/03/2022 23:05:07.679 | Bid: 1.10927 | Ask: 1.10929 | Time: 29/03/2022 23:05:07
29/03/2022 23:05:07.477 | Bid: 1.10927 | Ask: 1.10928 | Time: 29/03/2022 23:05:07
29/03/2022 23:05:04.379 | Bid: 1.10927 | Ask: 1.10929 | Time: 29/03/2022 23:05:04
29/03/2022 23:05:04.178 | Bid: 1.10931 | Ask: 1.10933 | Time: 29/03/2022 23:05:04
29/03/2022 23:05:02.903 | Bid: 1.10935 | Ask: 1.10936 | Time: 29/03/2022 23:05:02
29/03/2022 23:04:54.160 | Bid: 1.10935 | Ask: 1.10935 | Time: 29/03/2022 23:04:54
29/03/2022 23:04:53.863 | Bid: 1.10934 | Ask: 1.10934 | Time: 29/03/2022 23:04:53
29/03/2022 23:04:53.655 | Bid: 1.10933 | Ask: 1.10933 | Time: 29/03/2022 23:04:53
29/03/2022 23:04:52.772 | Bid: 1.10931 | Ask: 1.10932 | Time: 29/03/2022 23:04:52
29/03/2022 23:04:49.771 | Bid: 1.10931 | Ask: 1.10931 | Time: 29/03/2022 23:04:49
29/03/2022 23:04:49.270 | Bid: 1.1093 | Ask: 1.1093 | Time: 29/03/2022 23:04:49
29/03/2022 23:04:48.812 | Bid: 1.10931 | Ask: 1.10931 | Time: 29/03/2022 23:04:48
29/03/2022 23:04:48.610 | Bid: 1.10932 | Ask: 1.10932 | Time: 29/03/2022 23:04:48
29/03/2022 23:04:43.949 | Bid: 1.10933 | Ask: 1.10933 | Time: 29/03/2022 23:04:43
29/03/2022 23:04:43.684 | Bid: 1.10934 | Ask: 1.10934 | Time: 29/03/2022 23:04:43
29/03/2022 23:04:43.480 | Bid: 1.10936 | Ask: 1.10936 | Time: 29/03/2022 23:04:43
29/03/2022 23:04:36.142 | Bid: 1.10938 | Ask: 1.10938 | Time: 29/03/2022 23:04:36
29/03/2022 23:04:35.273 | Bid: 1.10938 | Ask: 1.10939 | Time: 29/03/2022 23:04:35
29/03/2022 23:04:25.332 | Bid: 1.10938 | Ask: 1.10938 | Time: 29/03/2022 23:04:25
29/03/2022 23:04:24.781 | Bid: 1.10938 | Ask: 1.10939 | Time: 29/03/2022 23:04:24
29/03/2022 23:04:23.446 | Bid: 1.10938 | Ask: 1.10938 | Time: 29/03/2022 23:04:23
29/03/2022 23:04:22.167 | Bid: 1.10939 | Ask: 1.1094 | Time: 29/03/2022 23:04:22
29/03/2022 23:04:21.958 | Bid: 1.10939 | Ask: 1.10939 | Time: 29/03/2022 23:04:21
29/03/2022 23:04:21.558 | Bid: 1.10939 | Ask: 1.1094 | Time: 29/03/2022 23:04:21
@amusleh
amusleh
11 Apr 2022, 12:02
Hi,
It looks like a Pip related issue with your system supported TLS not related to our package.
Here are some links that can help you:
[Solved] Could not find a version that satisfies the requirement - Exception Error (exerror.com)
@amusleh
amusleh
11 Apr 2022, 11:59
Hi,
You should open Automate related thread under automate section of forum not under cTrader desktop.
Regarding your question, you can use History, it contains all your account historical trades with all of their data, example:
using System.Linq;
using cAlgo.API;
namespace NewcBot
{
[Robot(AccessRights = AccessRights.None)]
public class NewcBot : Robot
{
protected override void OnStart()
{
var lastTwoTrades = History.OrderByDescending(trade => trade.ClosingTime).Take(2).ToArray();
foreach (var trade in lastTwoTrades)
{
Print("{0} | {1} | {2} | {3} | {4} | {5} | {6} | {7}", trade.SymbolName, trade.TradeType, trade.VolumeInUnits, trade.EntryPrice, trade.ClosingPrice, trade.Pips, trade.NetProfit, trade.Commissions); ;
}
}
}
}
@amusleh
amusleh
10 Apr 2022, 09:48
Hi,
I just tested by uninstalling and reinstalling it, and it works fine, result:
PS C:\Users\afhac\source\OpenApiPy> pip uninstall ctrader-open-api
Found existing installation: ctrader-open-api 0.9.0
Uninstalling ctrader-open-api-0.9.0:
Would remove:
c:\users\afhac\appdata\local\programs\python\python39\lib\site-packages\ctrader_open_api-0.9.0.dist-info\*
c:\users\afhac\appdata\local\programs\python\python39\lib\site-packages\ctrader_open_api\*
c:\users\afhac\appdata\local\programs\python\python39\lib\site-packages\license
Proceed (Y/n)? y
Successfully uninstalled ctrader-open-api-0.9.0
PS C:\Users\afhac\source\OpenApiPy> pip install ctrader-open-api
Collecting ctrader-open-api
Using cached ctrader_open_api-0.9.0-py3-none-any.whl (29 kB)
Requirement already satisfied: protobuf==3.19.1 in c:\users\afhac\appdata\local\programs\python\python39\lib\site-packages (from ctrader-open-api) (3.19.1)
Requirement already satisfied: Twisted==21.7.0 in c:\users\afhac\appdata\local\programs\python\python39\lib\site-packages (from ctrader-open-api) (21.7.0)
Requirement already satisfied: Automat>=0.8.0 in c:\users\afhac\appdata\local\programs\python\python39\lib\site-packages (from Twisted==21.7.0->ctrader-open-api) (20.2.0)
Requirement already satisfied: constantly>=15.1 in c:\users\afhac\appdata\local\programs\python\python39\lib\site-packages (from Twisted==21.7.0->ctrader-open-api) (15.1.0)
Requirement already satisfied: twisted-iocpsupport~=1.0.0 in c:\users\afhac\appdata\local\programs\python\python39\lib\site-packages (from Twisted==21.7.0->ctrader-open-api) (1.0.2)
Requirement already satisfied: typing-extensions>=3.6.5 in c:\users\afhac\appdata\local\programs\python\python39\lib\site-packages (from Twisted==21.7.0->ctrader-open-api) (4.0.0)
Requirement already satisfied: zope.interface>=4.4.2 in c:\users\afhac\appdata\local\programs\python\python39\lib\site-packages (from Twisted==21.7.0->ctrader-open-api) (5.4.0)
Requirement already satisfied: incremental>=21.3.0 in c:\users\afhac\appdata\local\programs\python\python39\lib\site-packages (from Twisted==21.7.0->ctrader-open-api) (21.3.0)
Requirement already satisfied: hyperlink>=17.1.1 in c:\users\afhac\appdata\local\programs\python\python39\lib\site-packages (from Twisted==21.7.0->ctrader-open-api) (21.0.0)
Requirement already satisfied: attrs>=19.2.0 in c:\users\afhac\appdata\local\programs\python\python39\lib\site-packages (from Twisted==21.7.0->ctrader-open-api) (21.2.0)
Requirement already satisfied: six in c:\users\afhac\appdata\local\programs\python\python39\lib\site-packages (from Automat>=0.8.0->Twisted==21.7.0->ctrader-open-api) (1.16.0)
Requirement already satisfied: idna>=2.5 in c:\users\afhac\appdata\local\programs\python\python39\lib\site-packages (from hyperlink>=17.1.1->Twisted==21.7.0->ctrader-open-api) (3.3)
Requirement already satisfied: setuptools in c:\users\afhac\appdata\local\programs\python\python39\lib\site-packages (from zope.interface>=4.4.2->Twisted==21.7.0->ctrader-open-api) (56.0.0)
Installing collected packages: ctrader-open-api
Successfully installed ctrader-open-api-0.9.0
PS C:\Users\afhac\source\OpenApiPy>
I tested on Windows 11.
Can you tell me on which OS you got that error? which version of Python and Pip you were using?
@amusleh
amusleh
10 Apr 2022, 09:43
Hi,
I check my own code with Lots set to 4, and the result was matching and it printed True.
I tried so find the issue on your code but as it's very long and complicated I gave up.
You can use this method to get volume splits/fragments:
/// <summary>
/// Splits the lots in volume units and returns an array of volumes
/// USe the returned array to execute orders for each volume
/// </summary>
/// <param name="lots">Volume in lots</param>
/// <param name="maxLotsPerSplit">Maximum lots per split/fragment</param>
/// <returns>double[]</returns>
private double[] GetVolumeSplits(double lots, double maxLotsPerSplit)
{
var modulus = lots % maxLotsPerSplit;
var numberOfFragments = Convert.ToInt32((lots - modulus) / maxLotsPerSplit);
if (modulus > 0) numberOfFragments++;
var lotsPerFragement = lots / numberOfFragments;
var unitsPerFragment = Symbol.QuantityToVolumeInUnits(lotsPerFragement);
var unitsPerFragementNormalized = Symbol.NormalizeVolumeInUnits(unitsPerFragment, RoundingMode.Up);
var volumes = new double[numberOfFragments];
for (var i = 0; i < numberOfFragments; i++)
{
volumes[i] = modulus > 0 && i == volumes.Length - 1
? unitsPerFragment - (unitsPerFragment + Symbol.VolumeInUnitsMin - unitsPerFragementNormalized)
: unitsPerFragementNormalized;
}
return volumes;
}
Once you calculated the x% volume, then pass it to this method with maximum lots per split/fragment, then it will split the volume and returns an array.
Use the array with a loop for executing orders.
@amusleh
amusleh
09 Apr 2022, 09:31
( Updated at: 09 Apr 2022, 09:34 )
Hi,
You can use this:
using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Internals;
namespace NewcBot
{
[Robot(AccessRights = AccessRights.None)]
public class NewcBot : Robot
{
[Parameter("Max Lost Per Fragment", DefaultValue = 1)]
public double MaxLotsPerFragment { get; set; }
[Parameter("Lots", DefaultValue = 3.75)]
public double Lots { get; set; }
protected override void OnStart()
{
var modulus = Lots % MaxLotsPerFragment;
var numberOfFragments = Convert.ToInt32((Lots - modulus) / MaxLotsPerFragment);
if (modulus > 0)
{
numberOfFragments++;
}
var lotsPerFragement = Lots / numberOfFragments;
var unitsPerFragment = Symbol.QuantityToVolumeInUnits(lotsPerFragement);
var unitsPerFragementNormalized = Symbol.NormalizeVolumeInUnits(unitsPerFragment, RoundingMode.Up);
var volumes = new double[numberOfFragments];
for (var i = 0; i < numberOfFragments; i++)
{
volumes[i] = modulus > 0 && i == volumes.Length - 1
? unitsPerFragment - (unitsPerFragment + Symbol.VolumeInUnitsMin - unitsPerFragementNormalized)
: unitsPerFragementNormalized;
ExecuteMarketOrder(TradeType.Buy, SymbolName, volumes[i]);
}
// Check if the sum of fragments is equal to total volume (lots = 3.75)
Print(volumes.Sum() == Symbol.QuantityToVolumeInUnits(Lots));
}
}
}
It can give you an idea on how to do it, but the code definitely needs some improvements and optimizations.
You can use decimal instead of double but as the cTrader automate API is built around double it will make it much complicated.
For these kind of calculations double is not a good type, as it can cause rounding errors and non deterministic results on different CPUs.
@amusleh
amusleh
08 Apr 2022, 18:13
Hi,
Please stop creating multiple threads for same topic, continue with your first thread at: cTDN Forum - Ctrader should use standard file browsing
@amusleh
amusleh
08 Apr 2022, 11:14
Hi,
It's not a GUID problem, cTrader 4.2 uses new SDK style projects and cTrader 4.1 uses old legacy style projects, these two aren't compatible with each other.
Here is an example of cTrader 4.2 .NET framework cBot project file:
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net40</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="cTrader.Automate" Version="1.*" />
</ItemGroup>
</Project>
And cTrader 4.1 cBot project file:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<LangVersion>7.2</LangVersion>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{14F07D19-11D3-4FAC-A0A8-22E8C4850A8B}</ProjectGuid>
<ProjectTypeGuids>{DD87C1B2-3799-4CA2-93B6-5288EE928820};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>cAlgo</RootNamespace>
<AssemblyName>Data Tester</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="cAlgo.API, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3499da3018340880, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\API\cAlgo.API.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Data Tester.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
cTrader 4.2 can use and build cTrader 4.1 cBots/Indicators, but cTrader 4.1 can't.
@amusleh
amusleh
08 Apr 2022, 11:06
Hi,
You cBot code has lots of issues, I can't fix all of them and I always recommend users to first learn C# basics then start developing cBots/Indicators.
I fixed some of your cBot issues, try this:
using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
public class DemoBot : Robot
{
[Parameter(DefaultValue = 10000, MinValue = 1000)]
public int FirstLot { get; set; }
[Parameter(DefaultValue = 10000, MinValue = 1000)]
public int LotStep { get; set; }
[Parameter("Stop_Loss", DefaultValue = 50, MinValue = 0)]
public int Stop_Loss { get; set; }
[Parameter("Take_Profit", DefaultValue = 180, MinValue = 10)]
public int TakeProfit { get; set; }
[Parameter("Tral_Start", DefaultValue = 50, MinValue = 10)]
public int Tral_Start { get; set; }
[Parameter("Tral_Stop", DefaultValue = 50, MinValue = 10)]
public int Tral_Stop { get; set; }
[Parameter(DefaultValue = 5, MinValue = 2)]
public int MaxOrders { get; set; }
private bool RobotStopped;
private string botLabel;
protected override void OnStart()
{
botLabel = string.Format("{0}_{1}_DemoBot", SymbolName, TimeFrame);
Positions.Opened += OnPositionOpened;
}
protected override void OnTick()
{
double Bid = Symbol.Bid;
double Ask = Symbol.Ask;
double Point = Symbol.TickSize;
if (Positions.Count > 0 && RobotStopped)
return;
else
RobotStopped = false;
if (Positions.Count == 0)
SendFirstOrder(FirstLot);
else
ControlSeries();
foreach (var position in Positions.FindAll(botLabel, SymbolName))
{
if (position.SymbolName == Symbol.Name)
{
if (position.TradeType == TradeType.Buy)
{
if (Bid - GetAveragePrice(TradeType.Buy) >= Tral_Start * Point)
if (Bid - Tral_Stop * Point >= position.StopLoss)
ModifyPosition(position, Bid - Tral_Stop * Point,
position.TakeProfit);
}
if (position.TradeType == TradeType.Sell)
{
if (GetAveragePrice(TradeType.Sell) - Ask >= Tral_Start * Point)
if (Ask + Tral_Stop * Point <= position.StopLoss || position.StopLoss
== 0)
ModifyPosition(position, Ask + Tral_Stop * Point,
position.TakeProfit);
}
}
}
}
protected override void OnError(Error CodeOfError)
{
if (CodeOfError.Code == ErrorCode.NoMoney)
{
RobotStopped = true;
Print("ERROR!!! No money for order open, robot is stopped!");
}
else if (CodeOfError.Code == ErrorCode.BadVolume)
{
RobotStopped = true;
Print("ERROR!!! Bad volume for order open, robot is stopped!");
}
}
private void SendFirstOrder(int OrderVolume)
{
int Signal = GetStdIlanSignal();
if (!(Signal < 0))
switch (Signal)
{
case 0:
ExecuteMarketOrder(TradeType.Buy, SymbolName, OrderVolume, botLabel);
break;
case 1:
ExecuteMarketOrder(TradeType.Sell, SymbolName, OrderVolume, botLabel);
break;
}
}
private void OnPositionOpened(PositionOpenedEventArgs args)
{
if (args.Position.Label.Equals(botLabel, StringComparison.Ordinal) == false) return;
double? StopLossPrice = null;
double? TakeProfitPrice = null;
if (Positions.Count == 1)
{
var position = args.Position;
if (position.TradeType == TradeType.Buy)
TakeProfitPrice = position.EntryPrice + TakeProfit * Symbol.TickSize;
if (position.TradeType == TradeType.Sell)
TakeProfitPrice = position.EntryPrice - TakeProfit * Symbol.TickSize;
}
else
switch (GetPositionsSide())
{
case 0:
TakeProfitPrice = GetAveragePrice(TradeType.Buy) + TakeProfit *
Symbol.TickSize;
break;
case 1:
TakeProfitPrice = GetAveragePrice(TradeType.Sell) - TakeProfit *
Symbol.TickSize;
break;
}
foreach (var position in Positions)
{
if (position.Label.Equals(botLabel, StringComparison.Ordinal) == false) continue;
if (StopLossPrice != null || TakeProfitPrice != null)
{
ModifyPosition(position, position.StopLoss, TakeProfitPrice);
}
}
}
private double GetAveragePrice(TradeType TypeOfTrade)
{
double Result = Symbol.Bid;
double AveragePrice = 0;
long Count = 0;
foreach (var position in Positions)
{
if (position.Label.Equals(botLabel, StringComparison.Ordinal) == false) continue;
if (position.TradeType == TypeOfTrade)
{
AveragePrice += position.EntryPrice * position.Volume;
Count += position.Volume;
}
}
if (AveragePrice > 0 && Count > 0)
Result = AveragePrice / Count;
return Result;
}
private int GetPositionsSide()
{
int Result = -1;
int i, BuySide = 0, SellSide = 0;
for (i = 0; i < Positions.Count; i++)
{
if (Positions[i].TradeType == TradeType.Buy)
BuySide++;
if (Positions[i].TradeType == TradeType.Sell)
SellSide++;
}
if (BuySide == Positions.Count)
Result = 0;
if (SellSide == Positions.Count)
Result = 1;
return Result;
}
private void ControlSeries()
{
const int BarCount = 25;
int gradient = MaxOrders - 1;
foreach (Position position in Positions.FindAll(botLabel, SymbolName))
{
if (-position.Pips > Stop_Loss)
ClosePosition(position);
}
int _pipstep = GetDynamicPipstep(BarCount, gradient);
if (Positions.Count < MaxOrders)
{
long NewVolume = Symbol.NormalizeVolume(FirstLot + FirstLot * Positions.Count,
RoundingMode.ToNearest);
int positionSide = GetPositionsSide();
switch (positionSide)
{
case 0:
if (Symbol.Ask < FindLastPrice(TradeType.Buy) - _pipstep *
Symbol.TickSize)
{
if (NewVolume >= LotStep)
ExecuteMarketOrder(TradeType.Buy, SymbolName, NewVolume,
botLabel);
}
break;
case 1:
if (Symbol.Bid > FindLastPrice(TradeType.Sell) + _pipstep *
Symbol.TickSize)
{
if (NewVolume >= LotStep)
ExecuteMarketOrder(TradeType.Sell, SymbolName, NewVolume,
botLabel);
}
break;
}
}
}
private int GetDynamicPipstep(int CountOfBars, int gradient)
{
int Result;
double HighestPrice = 0, LowestPrice = 0;
int StartBar = Bars.ClosePrices.Count - 2 - CountOfBars;
int EndBar = Bars.ClosePrices.Count - 2;
for (int i = StartBar; i < EndBar; i++)
{
if (HighestPrice == 0 && LowestPrice == 0)
{
HighestPrice = Bars.HighPrices[i];
LowestPrice = Bars.LowPrices[i];
continue;
}
if (Bars.HighPrices[i] > HighestPrice)
HighestPrice = Bars.HighPrices[i];
if (Bars.LowPrices[i] < LowestPrice)
LowestPrice = Bars.LowPrices[i];
}
Result = (int)((HighestPrice - LowestPrice) / Symbol.TickSize / gradient);
return Result;
}
private double FindLastPrice(TradeType TypeOfTrade)
{
double LastPrice = 0;
foreach (var position in Positions)
{
if (position.Label.Equals(botLabel, StringComparison.Ordinal) == false) continue;
if (TypeOfTrade == TradeType.Buy && position.TradeType == TypeOfTrade)
{
if (LastPrice == 0)
{
LastPrice = position.EntryPrice;
continue;
}
if (position.EntryPrice < LastPrice)
LastPrice = position.EntryPrice;
}
if (TypeOfTrade == TradeType.Sell && position.TradeType == TypeOfTrade)
{
if (LastPrice == 0)
{
LastPrice = position.EntryPrice;
continue;
}
if (position.EntryPrice > LastPrice)
LastPrice = position.EntryPrice;
}
}
return LastPrice;
}
private int GetStdIlanSignal()
{
int Result = -1;
int LastBarIndex = Bars.ClosePrices.Count - 2;
int PrevBarIndex = LastBarIndex - 1;
if (Bars.ClosePrices[LastBarIndex] > Bars.OpenPrices[LastBarIndex])
if (Bars.ClosePrices[PrevBarIndex] > Bars.OpenPrices[PrevBarIndex])
Result = 0;
if (Bars.ClosePrices[LastBarIndex] < Bars.OpenPrices[LastBarIndex])
if (Bars.ClosePrices[PrevBarIndex] < Bars.OpenPrices[PrevBarIndex])
Result = 1;
return Result;
}
}
}
@amusleh
amusleh
08 Apr 2022, 10:54
( Updated at: 08 Apr 2022, 11:12 )
RE: RE:
shaahin69 said:
amusleh said:
Hi,
Visual studio 2022 and .NET 6 support is added to cTrader 4.2 which is in beta testing now, you can try it by downloading Spotware cTrader Beta.
Thank you for your reply.
However, I already got cTrader 4.2 along with a new cBot project using .NET 6.
Although I can build the cBot ok without any issue, but debugging doesn't work.
Do I require https://marketplace.visualstudio.com/items?itemName=Spotwareextensions.cBotsandCustomIndicators for Visual Studio 2022 for debugging?
Hi,
If your project is a legacy project created by older versions of cTrader and targeting .NET framework then you can't use Visual Studio 2022 to open it, you can only open new cTrader 4.2 projects with Visual Studio 2022.
Regarding debugging, the way we were debugging old .NET framework cBots/Indicators has changed, and there is no Visual studio extension for new cTrader 4.2 projects, you can build a cBot/Indicator algo file with any .NET IDE just by referencing the cTrader automate Nuget package.
We are creating a new documentation for cTrader automate that covers all these topics, it will be released alongside cTrader 4.2.
@amusleh
amusleh
11 Apr 2022, 14:34
Hi,
You can use unique labels or comments for each group of split positions, like I used History.Count, then when you want to modify those positions just group them by label/comment and modify each one via a loop.
@amusleh