Untitled
unknown
plain_text
2 years ago
11 kB
19
Indexable
using cAlgo.API;
using cAlgo.API.Indicators;
using System;
using System.Collections.Generic;
namespace BTCUSDbot
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class BTCUSDbot: Robot
{
[Parameter("ATR Period", DefaultValue = 14)]
public int ATRPeriod
{
get;
set;
}
private TimeFrame higherTimeframe = TimeFrame.Minute15;
private double higherTimeframeThreshold = 0.5;
private AverageTrueRange atr;
private double lotSize;
private DirectionalMovementSystem dmi;
private MovingAverage fastMA;
private MovingAverage slowMA;
private DateTime lastBarTime;
private Color regularStopLossColor = Color.Red;
private Color trailingStopLossColor = Color.Blue;
private Color currentStopLossColor;
private double trailingStopDistanceInPips = 30;
private double minProfitForTrailing = 30; // Minimum profit in pips before trailing stop becomes active
private RelativeStrengthIndex rsi;
private double stopLossPercentage = 2; // Set your desired stop loss percentage
private double takeProfitPercentage = 2;
private double _volumeInUnits;
private AverageDirectionalMovementIndexRating _averageDirectionalMovementIndexRating;
private double last5;
[Parameter("Volume (Lots)", DefaultValue = 0.01)]
public double VolumeInLots
{
get;
set;
}
[Parameter("Label", DefaultValue = "Sample")]
public string Label
{
get;
set;
}
private int lookbackPeriod = 100;
double lowestLow;
double highestHigh;
bool calculateHighestHigh = false;
//support/resistance distance
double distance;
double distanceThreshold;
double pipsThreshold = 10000;
public Position[] BotPositions
{
get
{
return Positions.FindAll(Label);
}
}
protected override void OnStart()
{
atr = Indicators.AverageTrueRange(ATRPeriod, MovingAverageType.Simple);
dmi = Indicators.DirectionalMovementSystem(ATRPeriod);
distanceThreshold = pipsThreshold * Symbol.PipSize;
int fastMAPeriod = 50;
int slowMAPeriod = 200;
int rsiPeriod = 14;
rsi = Indicators.RelativeStrengthIndex(Bars.ClosePrices, rsiPeriod);
fastMA = Indicators.MovingAverage(Bars.ClosePrices, fastMAPeriod, MovingAverageType.Simple);
slowMA = Indicators.MovingAverage(Bars.ClosePrices, slowMAPeriod, MovingAverageType.Simple);
lastBarTime = Bars.OpenTimes.LastValue;
_volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots);
_averageDirectionalMovementIndexRating = Indicators.AverageDirectionalMovementIndexRating(30);
lowestLow = MarketSeries.Low.Minimum(lookbackPeriod);
highestHigh = MarketSeries.High.Maximum(lookbackPeriod);
}
protected override void OnBar()
{
last5 = Bars.ClosePrices.Count - 5;
foreach(var position in Positions)
{
double unrealizedProfitInPips = position.Pips;
if (unrealizedProfitInPips >= minProfitForTrailing)
{
string lineName = $"StopLossLine_{position.Id}";
double trailingStopPrice = Symbol.Bid - trailingStopDistanceInPips * Symbol.PipSize;
ModifyPosition(position, trailingStopPrice, position.TakeProfit);
currentStopLossColor = trailingStopLossColor;
Chart.RemoveObject(lineName); //for sl/tp lines
Chart.RemoveAllObjects(); //for support/resistance
// Draw Stop Loss Line if it exists
if (position.StopLoss.HasValue)
{
double stopLossPrice = position.StopLoss.Value;
Chart.DrawHorizontalLine(lineName, stopLossPrice, currentStopLossColor, 1, LineStyle.Solid);
}
}
}
//if(calculateHighestHigh == true)
// {
highestHigh = MarketSeries.High.Maximum(lookbackPeriod);
lowestLow = MarketSeries.Low.Minimum(lookbackPeriod);
Chart.DrawHorizontalLine("resistance line", highestHigh, Color.Gold, 1, LineStyle.LinesDots);
Chart.DrawHorizontalLine("support line", lowestLow, Color.White, 1, LineStyle.LinesDots);
// calculateHighestHigh =false;
// }
}
protected override void OnTick()
{
// if (!IsPriceAboveWeeklySMAs())
// {
// Print("Price is below SMAs on the weekly chart. Not trading.");
// return;
// }
distanceThreshold = pipsThreshold * Symbol.PipSize;
distance = highestHigh - lowestLow;
if (Bars.OpenTimes.LastValue > lastBarTime)
{
lastBarTime = Bars.OpenTimes.LastValue;
int index = Bars.ClosePrices.Count - 2; // Index of the last closed bar
bool isHigherTimeframeUptrend = IsHigherTimeframeUptrend();
if (Symbol.Bid < highestHigh) Chart.DrawHorizontalLine("support line", lowestLow, Color.White, 1, LineStyle.LinesDots);
Chart.DrawHorizontalLine("resistance line", highestHigh, Color.Gold, 1, LineStyle.LinesDots);
double atrValue = atr.Result[index];
// Define your threshold for a price spike (e.g., 2 times the ATR)
double spikeThreshold = 2 * atrValue;
double currentValue = MarketSeries.Close.LastValue; // Get the current closing price
double minValue = MarketSeries.Close.LastValue; // Replace YourMinValue with the minimum value of your range
double maxValue = MarketSeries.Close.LastValue + 10; // Rep
double pipBuffer = 10.0; // You can adjust this buffer value as needed
double buffer = Symbol.PipSize * pipBuffer;
if (rsi.Result[index] < 30 && currentValue > lowestLow && currentValue - lowestLow < buffer && Positions.Count < 5 && highestHigh > spikeThreshold)
{
ExecuteMarketOrder(TradeType.Buy, SymbolName, Symbol.NormalizeVolumeInUnits(Symbol.LotSize), "Buy Order", 25, 200, null);
lowestLow = highestHigh;
calculateHighestHigh = true;
}
else if (Symbol.Ask < lowestLow)
{
// double stopLossPrice = Symbol.Bid + (Symbol.Bid * stopLossPercentage / 100.0);
// double takeProfitPrice = Symbol.Bid - (Symbol.Bid * takeProfitPercentage / 100.0);
// if(Symbol.Bid < lowestLow && dmi.ADX.IsFalling()&&Positions.Count == 0 ) {
// ExecuteMarketOrder(TradeType.Sell, SymbolName, Symbol.NormalizeVolumeInUnits(Symbol.LotSize), "Sell Order", 20, 20, null);
// }
// lowestLow = highestHigh;
// calculateHighestHigh = true;
}
}
distance = highestHigh - lowestLow;
}
private void ClosePosition(TradeResult position)
{
ClosePosition(position);
}
private void ClosePositions(TradeType tradeType)
{
foreach(var position in BotPositions)
{
if (position.TradeType != tradeType) continue;
ClosePosition(position);
}
}
private bool IsHigherTimeframeUptrend()
{
// Calculate moving averages on the higher timeframe
double[] higherTimeframeFastMASeries = CalculateSimpleMovingAverage(Bars.ClosePrices, TimeFrame.Daily, 50);
double[] higherTimeframeSlowMASeries = CalculateSimpleMovingAverage(Bars.ClosePrices, TimeFrame.Daily, 200);
double[] higherTimeframe1FastMASeries = CalculateSimpleMovingAverage(Bars.ClosePrices, TimeFrame.Hour, 50);
double[] higherTimeframe1SlowMASeries = CalculateSimpleMovingAverage(Bars.ClosePrices, TimeFrame.Hour, 200);
double[] higherTimeframe2FastMASeries = CalculateSimpleMovingAverage(Bars.ClosePrices, TimeFrame.Minute15, 50);
double[] higherTimeframe2SlowMASeries = CalculateSimpleMovingAverage(Bars.ClosePrices, TimeFrame.Minute15, 200);
int lastIndex = Bars.ClosePrices.Count - 1;
// Check if the slow MA on higher timeframe is below the fast MA, indicating a potential downtrend
return higherTimeframe1SlowMASeries[lastIndex] < higherTimeframe1FastMASeries[lastIndex] && higherTimeframe2SlowMASeries[lastIndex] < higherTimeframe2FastMASeries[lastIndex] && higherTimeframeSlowMASeries[lastIndex] < higherTimeframeFastMASeries[lastIndex];
}
private bool IsPriceAboveWeeklySMAs()
{
// Calculate SMAs on the weekly chart
double[] day200SMA = CalculateSimpleMovingAverage(Bars.ClosePrices, TimeFrame.Daily, 200);
double[] hour200SMA = CalculateSimpleMovingAverage(Bars.ClosePrices, TimeFrame.Hour, 200);
double[] min15200SMA = CalculateSimpleMovingAverage(Bars.ClosePrices, TimeFrame.Minute15, 200);
int lastIndex = Bars.ClosePrices.Count - 1;
double currentPrice = MarketSeries.Close[lastIndex];
// Check if the current price is above all three SMAs
return currentPrice > day200SMA[lastIndex] && currentPrice > hour200SMA[lastIndex] && currentPrice > min15200SMA[lastIndex];
}
private double[] CalculateSimpleMovingAverage(DataSeries source, TimeFrame timeframe, int period)
{
double[] smaValues = new double[source.Count];
for (int i = 0; i < source.Count; i++)
{
if (i >= period - 1)
{
double sum = 0;
for (int j = i - period + 1; j <= i; j++)
{
sum += source[j];
}
smaValues[i] = sum / period;
}
else
{
smaValues[i] = source[i];
}
}
return smaValues;
}
}
}Editor is loading...