RevyAtm
RevyAtm
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Forms;
using System.Windows.Media;
using System.Xml.Serialization;
using NinjaTrader.Cbi;
using NinjaTrader.Gui;
using NinjaTrader.Gui.Chart;
using NinjaTrader.Gui.NinjaScript;
using NinjaTrader.Gui.SuperDom;
using NinjaTrader.Gui.Tools;
using NinjaTrader.Data;
using NinjaTrader.NinjaScript;
using NinjaTrader.Core.FloatingPoint;
using NinjaTrader.NinjaScript.Indicators;
using NinjaTrader.NinjaScript.DrawingTools;
#endregion
namespace NinjaTrader.NinjaScript.Strategies
{
public class RevyAtm : Strategy, ICustomTypeDescriptor //
{
// Variables for ATM strategy
private string atmStrategyId = string.Empty;
private string orderId = string.Empty;
private bool isAtmStrategyCreated = false;
// KillAll
private Instrument inst;
private Account chartTraderAccount;
private AccountSelector accountSelector;
// Status Panel
private string textLine0;
private string textLine1;
private string textLine2;
private string textLine3;
private string textLine4;
private string textLine5;
private string textLine6;
private string textLine7;
// PnL
private double totalPnL;
private double cumPnL;
private double dailyPnL;
private bool canTradeOK = true;
#region Properties
[NinjaScriptProperty]
[ReadOnly(true)]
[Display(Name="StrategyName", Order=1, GroupName="0. Release notes")]
public string StrategyName
{ get; set; }
[NinjaScriptProperty]
[ReadOnly(true)]
[Display(Name="Version", Order =2, GroupName="0. Release notes")]
public string Version
{ get; set; }
[NinjaScriptProperty]
[ReadOnly(true)]
[Display(Name="Credits", Order=3, GroupName="0. Release notes")]
public string Credits
{ get; set; }
[NinjaScriptProperty]
[Display(Name="Chart", Order=4, GroupName="0. Release notes")]
public string Chart
{ get; set; }
#endregion
[NinjaScriptProperty]
[Range(0, double.MaxValue)]
[Display(ResourceType = typeof(Custom.Resource), Name="Daily Loss Limit
($)", Description="No positive or negative sign, just integer", Order=6,
GroupName="01. Order Management")]
public double DailyLossLimit
{ get; set; }
[NinjaScriptProperty]
[Display(Name = "Enable Trades Per Direction", Description = "Switch
off Historical Trades to use this option.", Order = 0, GroupName = "02. Trades Per
Direction")]
[RefreshProperties(RefreshProperties.All)]
public bool TradesPerDirection
{
get{return tradesPerDirection;}
set{tradesPerDirection = (value);}
}
[NinjaScriptProperty]
[Display(Name="Long Per Direction", Description = "Number of long in a
row", Order = 1, GroupName = "02. Trades Per Direction")]
public int longPerDirection
{ get; set; }
[NinjaScriptProperty]
[Display(Name="Short Per Direction", Description = "Number of short in
a row", Order = 2, GroupName = "02. Trades Per Direction")]
public int shortPerDirection
{ get; set; }
[NinjaScriptProperty]
[PropertyEditor("NinjaTrader.Gui.Tools.TimeEditorKey")]
[Display(Name="End Trades", Order=2, GroupName="03. Time Frames")]
public DateTime End
{ get; set; }
[NinjaScriptProperty]
[Display(Name = "Enable Time 2", Description = "Enable 2 times.",
Order=3, GroupName = "03. Time Frames")]
[RefreshProperties(RefreshProperties.All)]
public bool Time2
{
get{return isEnableTime2;}
set{isEnableTime2 = (value);}
}
[NinjaScriptProperty]
[PropertyEditor("NinjaTrader.Gui.Tools.TimeEditorKey")]
[Display(Name="Start Time 2", Order=4, GroupName="03. Time Frames")]
public DateTime Start2
{ get; set; }
[NinjaScriptProperty]
[PropertyEditor("NinjaTrader.Gui.Tools.TimeEditorKey")]
[Display(Name="End Time 2", Order=5, GroupName="03. Time Frames")]
public DateTime End2
{ get; set; }
[NinjaScriptProperty]
[Display(Name = "Enable Time 3", Description = "Enable 3 times.",
Order=6, GroupName = "03. Time Frames")]
[RefreshProperties(RefreshProperties.All)]
public bool Time3
{
get{return isEnableTime3;}
set{isEnableTime3 = (value);}
}
[NinjaScriptProperty]
[PropertyEditor("NinjaTrader.Gui.Tools.TimeEditorKey")]
[Display(Name="Start Time 3", Order=7, GroupName="03. Time Frames")]
public DateTime Start3
{ get; set; }
[NinjaScriptProperty]
[PropertyEditor("NinjaTrader.Gui.Tools.TimeEditorKey")]
[Display(Name="End Time 3", Order=8, GroupName="03. Time Frames")]
public DateTime End3
{ get; set; }
[NinjaScriptProperty]
[Display(Name = "Enable Time 4", Description = "Enable 4 times.",
Order=9, GroupName = "03. Time Frames")]
[RefreshProperties(RefreshProperties.All)]
public bool Time4
{
get{return isEnableTime4;}
set{isEnableTime4 = (value);}
}
[NinjaScriptProperty]
[PropertyEditor("NinjaTrader.Gui.Tools.TimeEditorKey")]
[Display(Name="Start Time 4", Order=10, GroupName="03. Time Frames")]
public DateTime Start4
{ get; set; }
[NinjaScriptProperty]
[PropertyEditor("NinjaTrader.Gui.Tools.TimeEditorKey")]
[Display(Name="End Time 4", Order=11, GroupName="03. Time Frames")]
public DateTime End4
{ get; set; }
[NinjaScriptProperty]
[Display(Name = "Enable Time 5", Description = "Enable 5 times.",
Order=12, GroupName = "03. Time Frames")]
[RefreshProperties(RefreshProperties.All)]
public bool Time5
{
get{return isEnableTime5;}
set{isEnableTime5 = (value);}
}
[NinjaScriptProperty]
[PropertyEditor("NinjaTrader.Gui.Tools.TimeEditorKey")]
[Display(Name="Start Time 5", Order=13, GroupName="03. Time Frames")]
public DateTime Start5
{ get; set; }
[NinjaScriptProperty]
[PropertyEditor("NinjaTrader.Gui.Tools.TimeEditorKey")]
[Display(Name="End Time 5", Order=14, GroupName="03. Time Frames")]
public DateTime End5
{ get; set; }
[NinjaScriptProperty]
[Display(Name = "Enable Time 6", Description = "Enable 6 times.", Order
=15, GroupName = "03. Time Frames")]
[RefreshProperties(RefreshProperties.All)]
public bool Time6
{
get{return isEnableTime6;}
set{isEnableTime6 = (value);}
}
[NinjaScriptProperty]
[PropertyEditor("NinjaTrader.Gui.Tools.TimeEditorKey")]
[Display(Name="Start Time 6", Order=16, GroupName="03. Time Frames")]
public DateTime Start6
{ get; set; }
[NinjaScriptProperty]
[PropertyEditor("NinjaTrader.Gui.Tools.TimeEditorKey")]
[Display(Name="End Time 6", Order=17, GroupName="03. Time Frames")]
public DateTime End6
{ get; set; }
#endregion
#region Filters
[NinjaScriptProperty]
[Display(Name="RegChanPeriod", Order=1, GroupName="04. Filters
Settings")]
public int RegChanPeriod
{ get; set; }
[NinjaScriptProperty]
[Display(Name="LinRegPeriod", Order=2, GroupName="04. Filters
Settings")]
public int LinRegPeriod
{ get; set; }
[NinjaScriptProperty]
[Display(Name="ADXPeriod", Order=3, GroupName="04. Filters Settings")]
public int ADXPeriod
{ get; set; }
[NinjaScriptProperty]
[Display(Name="ADXThreshold", Order=4, GroupName="04. Filters
Settings")]
public int ADXThreshold
{ get; set; }
#endregion
[NinjaScriptProperty]
[Display(Name="STATUS PANEl Position", Description = "PNL Position",
Order = 1, GroupName = "STATUS PANEL")]
public TextPosition PositionPnl
{ get; set; }
[XmlIgnore()]
[Display(Name = "STATUS PANEl Color", Order = 1, GroupName = "STATUS
PANEL")]
public Brush colorPnl
{ get; set; }
[NinjaScriptProperty]
[Display(Name = "ATMStrategyTemplate", Order = 1, GroupName =
"Parameters")]
public string ATMStrategyTemplate { get; set; }
#endregion
Calculate = Calculate.OnEachTick;
EntriesPerDirection = 2; // This value
should limit the number of contracts that the strategy can open per direction.
// It has nothing to do with the parameter defining the entries per direction
that we define in the strategy and are controlled by code.
EntryHandling = EntryHandling.AllEntries;
IsExitOnSessionCloseStrategy = true;
ExitOnSessionCloseSeconds = 30;
IsFillLimitOnTouch = false;
MaximumBarsLookBack = MaximumBarsLookBack.TwoHundredFiftySix;
OrderFillResolution = OrderFillResolution.High;
Slippage = 0;
StartBehavior = StartBehavior.WaitUntilFlat;
TimeInForce = TimeInForce.Gtc;
TraceOrders = false;
RealtimeErrorHandling = RealtimeErrorHandling.StopCancelClose;
StopTargetHandling = StopTargetHandling.PerEntryExecution;
BarsRequiredToTrade = 20;
IsInstantiatedOnEachOptimizationIteration = false;
// Default Parameters
isStrategyEnabled = true;
isLongEnabled = true;
isShortEnabled = true;
RegChanPeriod = 30;
LinRegPeriod = 9;
ADXPeriod = 4;
ADXThreshold = 50;
tradesPerDirection = false;
longPerDirection = 5;
shortPerDirection = 5;
counterLong = 0;
counterShort = 0;
Start =
DateTime.Parse("06:40", System.Globalization.CultureInfo.InvariantCulture);
End =
DateTime.Parse("07:30", System.Globalization.CultureInfo.InvariantCulture);
Start2 =
DateTime.Parse("08:00", System.Globalization.CultureInfo.InvariantCulture);
End2 =
DateTime.Parse("08:30", System.Globalization.CultureInfo.InvariantCulture);
Start3 =
DateTime.Parse("09:00", System.Globalization.CultureInfo.InvariantCulture);
End3 =
DateTime.Parse("09:30", System.Globalization.CultureInfo.InvariantCulture);
Start4 =
DateTime.Parse("12:30", System.Globalization.CultureInfo.InvariantCulture);
End4 =
DateTime.Parse("13:00", System.Globalization.CultureInfo.InvariantCulture);
Start5 =
DateTime.Parse("15:00", System.Globalization.CultureInfo.InvariantCulture);
End5 =
DateTime.Parse("23:59", System.Globalization.CultureInfo.InvariantCulture);
Start6 =
DateTime.Parse("00:00", System.Globalization.CultureInfo.InvariantCulture);
End6 =
DateTime.Parse("06:39", System.Globalization.CultureInfo.InvariantCulture);
// Panel Status
showPnl = true;
PositionPnl =
TextPosition.TopRight;
colorPnl =
Brushes.AliceBlue; // Default value
// PnL Daily Limits
DailyProfitLimit = 10000;
DailyLossLimit = 2000;
}
else if (State == State.Configure)
{
RealtimeErrorHandling = RealtimeErrorHandling.IgnoreAllErrors;
}
else if (State == State.DataLoaded)
{
CurrentDayOHL1 = CurrentDayOHL(Close);
RegressionChannelHighLow1 =
RegressionChannelHighLow(Close, RegChanPeriod, 3.5);
LinReg1 = LinReg(Close,
LinRegPeriod);
T3TrendFilter1 = T3TrendFilter(Close, 0.1,
1, 2, 3, 4, 5, false);
ADX1 = ADX(Close, ADXPeriod);
}
else if (State == State.Historical)
{
// Chart Trader Buttons Load
Dispatcher.InvokeAsync((() => { CreateWPFControls();
}));
}
else if (State == State.Terminated)
{
// Chart Trader Buttons dispose
ChartControl?.Dispatcher.InvokeAsync(() => {
DisposeWPFControls(); });
}
}
#region DecoreButton
#endregion
CreateButtons();
// Initialize
InitializeButtonGrid();
// SetButtons
SetButtonLocations();
// AddButtons
AddButtonsToGrid();
if (TabSelected())
InsertWPFControls();
chartWindow.MainTabControl.SelectionChanged += TabChangedHandler;
}
#endregion
// Columns number
for (int i = 0; i < 2; i++)
{
lowerButtonsGrid.ColumnDefinitions.Add(new
System.Windows.Controls.ColumnDefinition());
}
// Row naumber
for (int i = 0; i <= 5; i++)
{
lowerButtonsGrid.RowDefinitions.Add(new
System.Windows.Controls.RowDefinition());
}
}
if (columnSpan > 1)
System.Windows.Controls.Grid.SetColumnSpan(button, columnSpan);
}
if (button == useAutoBtn)
{
isStrategyEnabled = !isStrategyEnabled;
if (isStrategyEnabled) DecoreEnabledButtons(useAutoBtn, "\
uD83D\uDD12 Strategy Enabled");
if (!isStrategyEnabled) DecoreDisabledButtons(useAutoBtn,
"\uD83D\uDD13 Strategy Disabled");
return;
}
if (button == useLongBtn)
{
isLongEnabled = !isLongEnabled;
if (isLongEnabled) DecoreEnabledButtons(useLongBtn, "LONG
Enabeld");
if (!isLongEnabled) DecoreDisabledButtons(useLongBtn, "LONG
Disabled");
return;
}
if (button == useShortBtn)
{
isShortEnabled = !isShortEnabled;
if (isShortEnabled) DecoreEnabledButtons(useShortBtn,
"SHORT Enabled");
if (!isShortEnabled) DecoreDisabledButtons(useShortBtn,
"SHORT Disabled");
return;
}
if (button == closeBtn)
{
CloseActPositions();
ForceRefresh();
return;
}
if (button == panicBtn)
{
FlattenAllPositions();
ForceRefresh();
return;
}
#region Dispose
public void DisposeWPFControls()
{
if (chartWindow != null)
chartWindow.MainTabControl.SelectionChanged -=
TabChangedHandler;
if (useAutoBtn != null)
useAutoBtn.Click -= OnButtonClick;
if (useLongBtn != null)
useLongBtn.Click -= OnButtonClick;
if (useShortBtn != null)
useShortBtn.Click -= OnButtonClick;
if (closeBtn != null)
closeBtn.Click -= OnButtonClick;
if (panicBtn != null)
panicBtn.Click -= OnButtonClick;
RemoveWPFControls();
}
#endregion
if (panelActive)
return;
panelActive = true;
}
#endregion
panelActive = false;
}
#endregion
#region TabSelcected
private bool TabSelected()
{
// loop through each tab and see if the tab this indicator is
added to is the selected item
foreach (System.Windows.Controls.TabItem tab in
chartWindow.MainTabControl.Items)
if ((tab.Content as Gui.Chart.ChartTab).ChartControl ==
ChartControl && tab == chartWindow.MainTabControl.SelectedItem)
tabSelected = true;
return tabSelected;
}
#endregion
#region TabHandler
private void TabChangedHandler(object sender,
System.Windows.Controls.SelectionChangedEventArgs e)
{
if (e.AddedItems.Count <= 0)
return;
if (TabSelected())
InsertWPFControls();
else
RemoveWPFControls();
}
#endregion
}
}
#endregion
#region DrawPnl
private void showPNLStatus() {
textLine0 = "ActiveTimer";
textLine1 = GetActiveTimer();
textLine2 = "longPerDirection";
textLine3 = $"{counterLong} / {longPerDirection} | " +
(TradesPerDirection ? "On" : "Off");
textLine4 = "shortPerDirection";
textLine5 = $"{counterShort} / {shortPerDirection} | " +
(TradesPerDirection ? "On" : "Off");;
textLine6 = "ACCT PnL ";
textLine7 = $"{dailyPnL:F2}"; // Pending
textLine7 = $" N/A "; // Pending
string statusPnlText = textLine0 + "\t" + textLine1 + "\n" +
textLine2 + "\t" + textLine3 + "\n" + textLine4 + "\t" + textLine5+ "\n" +
textLine6 + "\t" + textLine7+ "\n";
SimpleFont font = new SimpleFont("Arial", 15);
}
#endregion
Up = T3TrendFilter1.Values[0][0];
Down = T3TrendFilter1.Values[1][0];
if (showPnl) showPNLStatus();
if (CheckLongEntryConditions()
&& AtmStrategyNotActive()
&& (isLongEnabled)
&& (checkTimers())
)
{
if (!TradesPerDirection || (TradesPerDirection &&
counterLong <= longPerDirection))
{
counterLong +=1;
counterShort = 0;
CreateAtmStrategy(OrderAction.Buy, "LongSignal",
Low[0] + (-10 * TickSize), Brushes.Lime);
}
else
{
Print("Limit long trades in a row");
}
}
if (CheckShortEntryConditions()
&& AtmStrategyNotActive()
&& (isShortEnabled)
&& (checkTimers())
)
{
if (!isAtmStrategyCreated)
return;
UpdateAtmStrategyStatus();
if (atmStrategyId.Length > 0)
{
UpdateStopPrice();
PrintAtmStrategyInfo();
}
// checkPnL();
if (signalName == "ShortSignal")
Draw.ArrowDown(this, signalName + CurrentBars[0], false, 0,
signalPrice, signalBrush);
}
if (status.Length > 0)
{
PrintOrderStatus(status);
if (status[2] == "Filled" || status[2] == "Cancelled" ||
status[2] == "Rejected")
orderId = string.Empty;
}
}
else if (atmStrategyId.Length > 0 &&
GetAtmStrategyMarketPosition(atmStrategyId) == MarketPosition.Flat)
{
atmStrategyId = string.Empty;
}
}
if (marketPosition == MarketPosition.Long)
{
newStopPrice = Low[0] - 3 * TickSize;
if (newStopPrice < GetCurrentBid())
{
AtmStrategyChangeStopTarget(0, newStopPrice, "STOP6",
atmStrategyId);
}
}
else if (marketPosition == MarketPosition.Short)
{
newStopPrice = High[0] + 3 * TickSize;
if (newStopPrice > GetCurrentAsk())
{
AtmStrategyChangeStopTarget(0, newStopPrice, "STOP6",
atmStrategyId);
}
}
}
// Pending to review
// protected void checkPnL()
// {
// canTradeOK = true;
// }
// Print($"dailyPnL = {dailyPnL}");
// }
// }
// }
// }
#endregion
orderSelector showOrder;
#endregion
ModifyProperties(col);
return col;
#endregion
}