Untitled
plain_text
14 days ago
11 kB
1
Indexable
Never
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; } } }