I have taken a sample strategy for Tactical Allocation and have added these items:
- Choose # of assets open.
- Stop loss Pct.
- Same day stop loss.
However, it is not working right. for "Stop loss Pct" and "Same day stop loss". I have set the Stop Loss Pct to 10%.
Here is the Strategy Settings tab:
Here is the Position screen:
Here is my code:
Can you please take a look.
Thank you,
Larry
- Choose # of assets open.
- Stop loss Pct.
- Same day stop loss.
However, it is not working right. for "Stop loss Pct" and "Same day stop loss". I have set the Stop Loss Pct to 10%.
Here is the Strategy Settings tab:
Here is the Position screen:
Here is my code:
CODE:
using System; using WealthLab.Core; using WealthLab.Backtest; using WealthLab.Data; using WealthLab.Indicators; using System.Drawing; using System.Collections.Generic; namespace WealthScript11 { public class TacticalAssetRotation : UserStrategyBase { public TacticalAssetRotation() { AddParameter("Number of Buy Candidates", ParameterType.Int32, 6, 1, 10, 1); AddParameter("Stop Loss Pct", ParameterType.Int32, 10, 2, 80, 2); } //declare private variables below private TimeSeries avgROC; private string seriesKey = "Average ROC"; //the list of symbols that we should buy each bar private static List<BarHistory> buys = new List<BarHistory>(); //create the weight indicator and stash it into the BarHistory object for reference in PreExecute public override void Initialize(BarHistory bars) { //load the parameters numParticipants = Parameters[0].AsInt; stopLossPct = Parameters[1].AsInt; avgROC = (ROC.Series(bars.Close, 60) + ROC.Series(bars.Close, 120) + ROC.Series(bars.Close, 200)) / 3; bars.Cache[seriesKey] = avgROC; } //this is called prior to the Execute loop, determine which symbols have the lowest average ROC public override void PreExecute(DateTime dt, List<BarHistory> participants) { //store the symbols' AvgROC value in their BarHistory instances foreach (BarHistory bh in participants) { TimeSeries symbolRoc = (TimeSeries)bh.Cache[seriesKey]; int idx = GetCurrentIndex(bh); //this returns the index of the BarHistory for the bar currently being processed double rocVal = symbolRoc[idx]; //if the indicator isn't valid set a high value to avoid selection in rotation if (idx < symbolRoc.FirstValidIndex) rocVal = 1.0e6; bh.UserData = rocVal; //save the current AvgROC value along with the BarHistory instance } //sort the participants by AvgROC value (lowest to highest) participants.Sort((a, b) => a.UserDataAsDouble.CompareTo(b.UserDataAsDouble)); //keep the top 3 symbols buys.Clear(); //for (int n = 0; n < 3; n++) for (int n = 0; n < numParticipants; n++) // LARRY NEW LINE OF CODE { if (n >= participants.Count) break; buys.Add(participants[n]); } } //execute the strategy rules here, this is executed once for each bar in the backtest history public override void Execute(BarHistory bars, int idx) { bool inBuyList = buys.Contains(bars); if (!HasOpenPosition(bars, PositionType.Long)) { //create the transation for use with same say stops Transaction trans = null; //no entry if not in the buy list if (!inBuyList) return; if (inBuyList) { trans = PlaceTrade(bars, TransactionType.Buy, OrderType.Market, 0, 0, "Buy Tactical"); } } else { //sell logic, sell if it's not in the buys list if (!inBuyList) { //PlaceTrade(bars, TransactionType.Sell, OrderType.Market); Backtester.CancelationCode = 284; PlaceTrade(bars, TransactionType.Sell, OrderType.Market, 0, 0, "Sell Tactical"); } else // this is not working right for stop loss exit //stop loss exit PlaceTrade(bars, TransactionType.Sell, OrderType.Stop, StopLoss(bars, idx), 0, "Stop Loss Tactical"); } // this is not working for Same bar exit } //same bar exits: profit or loss from execution price public override void AssignAutoStopTargetPrices(Transaction trans, double basisPrice, double executionPrice) { trans.AutoStopLossPrice = Math.Round(executionPrice * (1 - (stopLossPct / 100)), 2); } //calcualte the stoploss price and return it private double StopLoss(BarHistory bars, int idx) { return Math.Round(LastOpenPosition.EntryPrice * (1 - (stopLossPct / 100)), 2); } //private variables int numParticipants,stopLossPct; } }
Can you please take a look.
Thank you,
Larry
Rename
Re: stopLossPct / 100. When doing a division of two double values you should indicate that explicitly, otherwise you may get a zero because in C# this is considered an integer division. You have to perform an implicit cast to double or specify the divisor as a double e.g.
double d1 = 123 / 456d;
double d2 = 123 / (double)456;
double d3 = 123 / 456.0;
double d1 = 123 / 456d;
double d2 = 123 / (double)456;
double d3 = 123 / 456.0;
Eugene,
Got it.
Thank you,
Larry
Got it.
Thank you,
Larry
Your Response
Post
Edit Post
Login is required