using System; using System.Linq; // ReSharper disable UnusedAutoPropertyAccessor.Global // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedMember.Global namespace TSLab.Script.Handlers { [HandlerName("Entry Price")] [HandlerCategory("Position")] public class EntryPrice : IPosition2Double { public double Execute(IPosition pos, int barNum) { if (pos == null) { return 0; } return pos.EntryPrice; } } [HandlerName("Entry Date")] [HandlerCategory("Position")] public class EntryDate : IPosition2Double { public double Execute(IPosition pos, int barNum) { if (pos == null) { return 0; } var dt = pos.EntryBar.Date; return (dt.Year % 100) * 10000.0 + dt.Month * 100.0 + dt.Day; } } [HandlerName("Entry Time")] [HandlerCategory("Position")] public class EntryTime : IPosition2Double { public double Execute(IPosition pos, int barNum) { if (pos == null) { return 0; } var dt = pos.EntryBar.Date; return dt.Hour * 10000.0 + dt.Minute * 100.0 + dt.Second; } } [HandlerName("Bars Held")] [HandlerCategory("Position")] public class BarsHeld : IPosition2Double { public double Execute(IPosition pos, int barNum) { if(pos == null) { return -1; } return pos.IsActive ? barNum - pos.EntryBarNum : pos.BarsHeld; } } [HandlerCategory("Position")] public class Profit : IPosition2Double { public double Execute(IPosition pos, int barNum) { if (pos == null) { return 0; } return pos.OpenProfit(barNum); } } [HandlerName("Profit %")] [HandlerCategory("Position")] public class ProfitPct : IPosition2Double { public double Execute(IPosition pos, int barNum) { if (pos == null) { return 0; } return pos.OpenProfitPct(barNum); } } [HandlerCategory("Position")] public class MAE : IPosition2Double { public double Execute(IPosition pos, int barNum) { if (pos == null) { return 0; } return pos.OpenMAE(barNum); } } [HandlerName("MAE %")] [HandlerCategory("Position")] public class MAEPct : IPosition2Double { public double Execute(IPosition pos, int barNum) { if (pos == null) { return 0; } return pos.OpenMAEPct(barNum); } } [HandlerCategory("Position")] public class MFE : IPosition2Double { public double Execute(IPosition pos, int barNum) { if (pos == null) { return 0; } return pos.OpenMFE(barNum); } } [HandlerName("MFE %")] [HandlerCategory("Position")] public class MFEPct : IPosition2Double { public double Execute(IPosition pos, int barNum) { if (pos == null) { return 0; } return pos.OpenMFEPct(barNum); } } [HandlerName("Trail Stop")] [HandlerCategory("Position")] public class TrailStop : IPosition2Double { [HandlerParameter(true, "1.5", Min = "0.1", Max = "5", Step = "0.1", Name = "Stop Loss")] public double StopLoss { get; set; } [HandlerParameter(true, "0.5", Min = "0.1", Max = "3", Step = "0.1", Name = "Trail Enable")] public double TrailEnable { get; set; } [HandlerParameter(true, "0.5", Min = "0.1", Max = "3", Step = "0.1", Name = "Trail Loss")] public double TrailLoss { get; set; } public double Execute(IPosition pos, int barNum) { if (pos == null) { return 0; } double stop; var curProfit = pos.OpenMFEPct(barNum); if (curProfit > TrailEnable) { double shift = (curProfit - TrailLoss) / 100; stop = pos.EntryPrice * (1 + (pos.IsLong ? shift : -shift)); } else { double shift = (0 - StopLoss) / 100; stop = pos.EntryPrice * (1 + (pos.IsLong ? shift : -shift)); } var lastStop = pos.GetStop(barNum); if(lastStop == 0) { return stop; } return pos.IsLong ? Math.Max(stop, lastStop) : Math.Min(stop, lastStop); } } [HandlerName("Trail Stop Abs")] [HandlerCategory("Position")] public class TrailStopAbs : IPosition2Double { [HandlerParameter(true, "150", Min = "10", Max = "500", Step = "5")] public double StopLoss { get; set; } [HandlerParameter(true, "50", Min = "10", Max = "500", Step = "5")] public double TrailEnable { get; set; } [HandlerParameter(true, "50", Min = "10", Max = "500", Step = "5")] public double TrailLoss { get; set; } public double Execute(IPosition pos, int barNum) { if (pos == null) { return 0; } double stop; var curProfit = pos.OpenMFE(barNum) / pos.Shares; if (curProfit > TrailEnable) { double shift = curProfit - TrailLoss; stop = pos.EntryPrice + (pos.IsLong ? shift : -shift); } else { double shift = -StopLoss; stop = pos.EntryPrice + (pos.IsLong ? shift : -shift); } var lastStop = pos.GetStop(barNum); if (lastStop == 0) { return stop; } return pos.IsLong ? Math.Max(stop, lastStop) : Math.Min(stop, lastStop); } } [HandlerName("Has Position Active")] [HandlerCategory("Position")] public class HasPositionActive : IBar2BoolHandler { public bool Execute(ISecurity source, int barNum) { var pos = source.Positions.LastPositionActive; if (pos != null) { return pos.EntryBarNum <= barNum; } pos = source.Positions.LastPositionClosed; return !(pos == null || pos.ExitBarNum <= barNum); } } [HandlerName("Has Long Position Active")] [HandlerCategory("Position")] public class HasLongPositionActive : IBar2BoolHandler { public bool Execute(ISecurity source, int barNum) { var pos = source.Positions.LastLongPositionActive; if (pos != null) { return pos.EntryBarNum <= barNum; } pos = source.Positions.LastLongPositionClosed; return !(pos == null || pos.ExitBarNum <= barNum); } } [HandlerName("Has Short Position Active")] [HandlerCategory("Position")] public class HasShortPositionActive : IBar2BoolHandler { public bool Execute(ISecurity source, int barNum) { var pos = source.Positions.LastShortPositionActive; if (pos != null) { return pos.EntryBarNum <= barNum; } pos = source.Positions.LastShortPositionClosed; return !(pos == null || pos.ExitBarNum <= barNum); } } [HandlerName("Last Closed Is Long")] [HandlerCategory("Position")] public class LastClosedIsLong : IBar2BoolHandler { public bool Execute(ISecurity source, int barNum) { if(source.Positions.Count() == 0) { return false; } var last = source.Positions.Last(); return !last.IsActive && last.IsLong && last.ExitBarNum <= barNum; } } [HandlerName("Last Closed Is Short")] [HandlerCategory("Position")] public class LastClosedIsShort : IBar2BoolHandler { public bool Execute(ISecurity source, int barNum) { if (source.Positions.Count() == 0) { return false; } var last = source.Positions.Last(); return !last.IsActive && last.IsShort && last.ExitBarNum <= barNum; } } } // ReSharper restore MemberCanBePrivate.Global // ReSharper restore UnusedAutoPropertyAccessor.Global // ReSharper restore UnusedMember.Global