I am trying to implement the following condition: If the SPY return for the period is greater than the TLT return, then we buy shares from the list, otherwise we buy TLT.
Previously, this could be done quite easily using the SetContext function, but now are there any simple options?
Previously, this could be done quite easily using the SetContext function, but now are there any simple options?
Rename
I always thought the SetContet method was clumsy. It only let you change the context to one symbol, so it got confusing if you wanted to deal with multiple external symbols and remember which context you're in. So I scrapped that for WL7+ and added some much easier methods. In a C# Strategy you can call GetHistory to get a BarHistory for any symbol. In Building Blocks you can use SymbolInd. Here's an example that compares the return of SPY with the return of TLT.
CODE:
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Data; using WealthLab.Indicators; using System.Collections.Generic; namespace WealthScript1 { public class MyStrategy : UserStrategyBase { //create indicators and other objects here, this is executed prior to the main trading loop public override void Initialize(BarHistory bars) { BarHistory spy = GetHistory(bars, "SPY"); BarHistory tlt = GetHistory(bars, "TLT"); ROC rocSPY = ROC.Series(spy.Close, 20); ROC rocTLT = ROC.Series(tlt.Close, 20); TimeSeries diff = rocSPY - rocTLT; PlotTimeSeries(diff, "Return SPY - Return TLT", "Diff", WLColor.Teal, PlotStyle.Histogram); } //execute the strategy rules here, this is executed once for each bar in the backtest history public override void Execute(BarHistory bars, int idx) { if (!HasOpenPosition(bars, PositionType.Long)) { //code your buy conditions here } else { //code your sell conditions here } } //declare private variables below } }
Just to add to Dion's reply, in case it's not evident to topic starter who seems to be migrating from the old version. Simply pass that BarHistory instance to the PlaceTrade method (first argument). For example, instead of the usual "bh" or "bars" you pass on that "spy" or "tlt" from @Glitch's code. Refer to the QuickRef for a self-started example.
I had to read Post #2 three times before I got it. With an example, I would have got it in one reading. (No, I didn't realize one could PlaceTrade like that. Thanks for pointing that out.)
I rewrote the code slightly (for scoping and numerical analysis purposes), but it's the same concept.
I rewrote the code slightly (for scoping and numerical analysis purposes), but it's the same concept.
CODE:
namespace WealthScript3 { public class MyStrategy : UserStrategyBase { BarHistory spy, tlt; IndicatorBase diff; public override void Initialize(BarHistory bars) { spy = GetHistory(bars, "SPY"); tlt = GetHistory(bars, "TLT"); ROC rocSPY = ROC.Series(spy.Close, 1); ROC rocTLT = ROC.Series(tlt.Close, 1); diff = EMA.Series(rocSPY-rocTLT,12); //the differences are salient, so average them PlotTimeSeries(diff, "Return SPY - Return TLT", "Diff", WLColor.Teal, PlotStyle.Histogram); } public override void Execute(BarHistory bars, int idx) { if (HasOpenPosition(bars, PositionType.Long)) { //sell conditions below } else { //buy conditions below if (...) PlaceTrade(bars, TransactionType.Buy, OrderType.Market); else if (...) PlaceTrade(tlt, TransactionType.Buy, OrderType.Market); else if (...) PlaceTrade(spy, TransactionType.Buy, OrderType.Market); } } } }
I'm not sure what you're demonstrating, but the code in Post #3 ^^^ only checks if there's long open position for "bars" (the charted symbol) and if there is not, it will buy positions for bars.Symbol, TLT, and SPY.
Thank you Glitch, Eugene, Cone and superticker for your answers.
Sorry, but I still don't understand.
Glitch, you created TimeSeries diff, but how do I access this variable in PreExecute? (Since I also have characters sorted by ROC in PreExecute).
And after that, one more question, if possible, let’s say I want to find among the partcipants only the symbol whose value is equal to TLT or exclude TLT and SPY from sorting, how can this be done?
Big thanks in advance!
Sorry, but I still don't understand.
Glitch, you created TimeSeries diff, but how do I access this variable in PreExecute? (Since I also have characters sorted by ROC in PreExecute).
And after that, one more question, if possible, let’s say I want to find among the partcipants only the symbol whose value is equal to TLT or exclude TLT and SPY from sorting, how can this be done?
Big thanks in advance!
First, let's find out if you need to use PreExecute()? Why do you?
Second, let's modify Glitch's code a bit to rescope the variables to the Strategy class. Then you can access them in any method, like Execute(). By convention, it's a good practice to use _ as a prefix to [private/internal] class-scoped variables.
Second, let's modify Glitch's code a bit to rescope the variables to the Strategy class. Then you can access them in any method, like Execute(). By convention, it's a good practice to use _ as a prefix to [private/internal] class-scoped variables.
CODE:
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Data; using WealthLab.Indicators; using System.Collections.Generic; namespace WealthScript1 { public class MyStrategy : UserStrategyBase { //create indicators and other objects here, this is executed prior to the main trading loop public override void Initialize(BarHistory bars) { _spy = GetHistory(bars, "SPY"); _tlt = GetHistory(bars, "TLT"); _rocSPY = ROC.Series(_spy.Close, 20); _rocTLT = ROC.Series(_tlt.Close, 20); _diff = _rocSPY - _rocTLT; PlotTimeSeries(_diff, "Return SPY - Return TLT", "Diff", WLColor.Teal, PlotStyle.Histogram); } //execute the strategy rules here, this is executed once for each bar in the backtest history public override void Execute(BarHistory bars, int idx) { if (bars.Symbol == _spy.Symbol || bars.Symbol == _tlt.Symbol) { // do something - like skip Execute entirely return; } if (!HasOpenPosition(bars, PositionType.Long)) { //code your buy conditions here } else { //code your sell conditions here } } //declare private variables below BarHistory _spy; BarHistory _tlt; ROC _rocSPY; ROC _rocTLT; TimeSeries _diff; } }
Cone, thank you for answer!
So, I am trying to implement Dual momentum. The logic of the strategy is this: what if the 12-month return on SPY is greater than TLT? Buy the stocks that showed the maximum return from the list (let it be 10 out of 100 for example). If not, buy TLT. If the candidates (stocks) do not change, rebalance.
As a result, before I start sorting candidates, I need to understand the profitability of SPY over TLT.
Also, since in my dataset, in addition to stocks, I also have SPY and TLT, I would like to somehow simply exclude them from there. The same problem is when I just need to open a position using TLT - how can I figure out which participant has the TLT ticker so as not to go through everything?
As far as I understand, the search for candidates for purchase is carried out in PreExecute, if this is not so, can I implement this logic somehow differently?
So, I am trying to implement Dual momentum. The logic of the strategy is this: what if the 12-month return on SPY is greater than TLT? Buy the stocks that showed the maximum return from the list (let it be 10 out of 100 for example). If not, buy TLT. If the candidates (stocks) do not change, rebalance.
As a result, before I start sorting candidates, I need to understand the profitability of SPY over TLT.
Also, since in my dataset, in addition to stocks, I also have SPY and TLT, I would like to somehow simply exclude them from there. The same problem is when I just need to open a position using TLT - how can I figure out which participant has the TLT ticker so as not to go through everything?
As far as I understand, the search for candidates for purchase is carried out in PreExecute, if this is not so, can I implement this logic somehow differently?
QUOTE:That's a mistake.
since in my dataset, in addition to stocks, I also have SPY and TLT
Step 1: Don't include them in your DataSet. You only need references to them, which is what GetHistory() does.
Step 2:
For the PreExecute ranking, just look at the code produced by dragging the Condition "Symbol Ranking by Indicator".
QUOTE:
I'm not sure what you're demonstrating,
I'm simply demonstrating what was pointed out in Post #2, nothing more. One can use PlaceTrade to trade spy, tlt, and bars directly without calling WL6 SetContext. Of course, you wouldn't list three PlaceTrades in a row without some intervening code. I'll clarify that in the Post #3 code.
QUOTE:
... the search [ranks] for candidates for purchase is carried out in PreExecute,...
That's correct. I would copy the PreExecute example given at https://www.wealth-lab.com/Support/ApiReference/UserStrategyBase for RSI. Just change it to ROC instead so you're ranking by best ROC.
Here is how you'd do it in Pre-Execute.
CODE:
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Data; using WealthLab.Indicators; using System.Collections.Generic; namespace WealthScript1 { public class MyStrategy : UserStrategyBase { //create indicators and other objects here, this is executed prior to the main trading loop public override void Initialize(BarHistory bars) { } //what if the 12-month return on SPY is greater than TLT? public override void PreExecute(DateTime dt, List<BarHistory> participants) { if (_diff == null) { BarHistory spy = GetHistoryUnsynched("SPY", HistoryScale.Monthly); BarHistory tlt = GetHistory(spy, "TLT"); ROC rocSPY = ROC.Series(spy.Close, 12); ROC rocTLT = ROC.Series(tlt.Close, 12); _diff = rocSPY - rocTLT; } int idx = _diff.IndexOf(dt); if (idx >= 0) { WriteToDebugLog(dt.ToShortDateString() + " " + _diff[idx], false); if (_diff[idx] > 0) { //12-month return of SPY is > TLT } } } //execute the strategy rules here, this is executed once for each bar in the backtest history public override void Execute(BarHistory bars, int idx) { if (!HasOpenPosition(bars, PositionType.Long)) { //code your buy conditions here } else { //code your sell conditions here } } //declare private variables below private static TimeSeries _diff; } }
Thank you guys so much, I finally understood how to implement this!
Your Response
Post
Edit Post
Login is required