AccountMargin based on S&P's Close to Moving Average

I am trying to have the AccountMargin be a dynamic variable based on the S&P's Current Close to the Moving Average of the S&P.
I have the below but it does not change with the "MyMargin" variable always equal to 2.

The code does not produce an error when running or generate an error when verifying syntax.

Thanks,

Mike

SPY_Close = Foreign("SPY", "C");
SPY_MA=MA(SPY_CLOSE,200);
for( i = 0; i < BarCount; i++ ) {
MyMargin=IIf(SPY_Close[i]>SPY_MA[i],2,1);
SetOption("AccountMargin",100/MyMargin[i]);
}

Use static account margin value with dynamic position size.

SPY_close = Foreign("SPY", "C");
SPY_trendup = SPY_close > MA(SPY_close, 200);

SetPositionSize(IIf(SPY_trendup, 10, 5), spsPercentOfEquity);

Hi TrendSurfer,

Thank you for the reply. My apologies for not posting the entire loop. I am using the CBT and have "MyMargin" in a few places and am not using SetPositionSize.
The loop is below but I still cannot get the MyMargin to be conditioned via the S&P. I appreciate your help.

Mike


SPY_close = Foreign("SPY", "C");
SPY_trendup = SPY_close > MA(SPY_close, 200);

IIf(SPY_trendup,MyMargin=2, 1);

//SPY_Close = Foreign("SPY", "C");
//SPY_MA=MA(SPY_CLOSE,200);
//for( i = 0; i < BarCount; i++ ) {
//MyMargin=IIf(SPY_Close[i]>SPY_MA[i],2,1);
//SetOption("AccountMargin",100/MyMargin[i]);
//}

SPY_High = Foreign("SPY", "H");
SPY_Low = Foreign("SPY", "L");

TLT_Close = Foreign("TLT", "C");
TLT_Close20 = Ref(Foreign("TLT", "C"),-20);
TLT_Low = Foreign("TLT", "L");
IEF_Close = Foreign("IEF", "C");
IEF_Close20 = Ref(Foreign("IEF", "C"),-20);
IEF_Low = Foreign("IEF", "L");

//TLT_20D_Return=(TLT_Close-TLT_Close20)/ TLT_Close20 * 100;
//IEF_20D_Return=(IEF_Close-IEF_Close20)/ IEF_Close20 * 100;

TLT_20D_Return=ROC(TLT_Close,1);
IEF_20D_Return=ROC(IEF_Close,1);



function Trace(tt, str) {
	_TRACE(DateTimeToStr(tt)+" "+str);
}

function XMA(period) {
	res = IIf(AvgType == "SMA", MA(C, period), EMA(C, period)); 
	//res = IIf(AvgType == "SMA",LinearReg( Close, period ) , EMA(C, period)); //LinearReg( Close, 20 ); 
	return res;
}

//assume timeframe = Daily
symbol = Name();
dt = DateTime();
dn = DateNum();
dow = DayOfWeek();
mn = Month();

newMonth = mn != Ref(mn, -1);

SetCustomBacktestProc("");

//SetOption("AccountMargin",100/MyMargin);
if( Status( "action" ) == actionPortfolio ) {

	_TRACE("Symbol Count "+symbolCount);

    bo = GetBacktesterObject();
    bo.PreProcess();
		
    for( i = 0; i < BarCount; i++ ) {
     bo.HandleStops(i);
LongList = "";
ShortList = "";

		if (GetOption("PortfolioReportMode") != 0) { 
			bo.RawTextOutput( DateTimeToStr( dt[ i ] ) );        
		}


		bo.UpdateStats(i, 0);
		posCount = 0;
		for (sig = bo.GetFirstSignal(i); sig; sig = bo.GetNextSignal(i)) {
			if (sig.IsEntry()) {
				posCount++;
			}
			else if (sig.IsExit()) {
				bo.ExitTrade(i, sig.Symbol, sig.Price);
			}
		}

		bo.UpdateStats(i, 1);

		if (AllocMethod == "Equal") {
			posSize = (bo.Cash *MyMargin[i]) / symbolCount;
		}
		else {
		
		posSize = (bo.Cash *MyMargin[i]) / Max(MinPosCount, posCount);
		}

		for (sig = bo.GetFirstSignal(i); sig; sig = bo.GetNextSignal(i)) {
			if (sig.IsEntry()) {
				bo.EnterTrade(i, sig.Symbol, sig.IsLong(), sig.Price, posSize);
			}
		}
		bo.UpdateStats(i, 2);
    } 
    bo.PostProcess();
}

???????????????????????

I tried your original suggestion but I am not setting position size in the script via "SetPositionSize" but rather by

if (AllocMethod == "Equal") {
			posSize = (bo.Cash *MyMargin[i]) / symbolCount;
		}
		else {
		
		posSize = (bo.Cash *MyMargin[i]) / Max(MinPosCount, posCount);
		}

So I need to have MyMargin be dynamic. I only tried to put the logic you wrote in terms of MyMargin but it defaults to "2" in every case.

Thanks,

Mike

Is this the correct way to use 'IIf'? No!

1 Like

I am not sure what you mean. What you have just posted will always keep MyMargin set at 2, and it never changes to 1,

It's not what I have posted, it's what you have posted.

Isn't this the correct way?

myMargin = IIf(SPY_trendup, 2, 1);

My error, I had left off the "myMargin =". As you correctly caught. It works as expected now.

Thank you!!

Mike

1 Like

I have two functions below, expression 1 and expression 2. I am clicking on SPY in a watchlist and have the Analysis set to "Current".
With Expression 1, the code MyMargin22 will condition per the SPY and the SPY's MA.
With Expression 2, the code Mymargin22 will default to 1 in all cases.
I understand there can be synch issues with "Foreign" but in this case both symbols are the same.

Thanks,

Mike

//Expression 1
SPY_close = Foreign("SPY", "C");
SPY_trendup = SPY_close > MA(SPY_close, 2);
myMargin22 = IIf(SPY_trendup, 2.0, 1.0);

//Expression 2
SPY_trendup = close > MA(close, 2);//clicking on SPY in watchlist & have set to "Current"
myMargin22 = IIf(SPY_trendup, 2.0, 1.0);
type or paste code here

See how-do-i-debug-my-formula.

//Expression 1
SPY_close = Foreign("$XAO.au", "C");
SPY_trendup_foreign = SPY_close > MA(SPY_close, 2);
myMargin22_foreign = IIf(SPY_trendup_foreign, 2, 1);

//Expression 2
SPY_trendup = close > MA(close, 2);//clicking on SPY in watchlist & have set to "Current"
myMargin22 = IIf(SPY_trendup, 2, 1);

Filter = 1;

AddColumn(Close, "Close", 1.0);
AddColumn(MA(Close, 2), "MA(Close, 2)", 1.0);
AddColumn(SPY_trendup_foreign, "SPY_trendup_foreign", 1.0);
AddColumn(myMargin22_foreign, "myMargin22_foreign", 1.0);
AddColumn(SPY_trendup, "SPY_trendup", 1.0);
AddColumn(myMargin22, "myMargin22", 1.0);

All OK!

image

TrendSurfer,
Thank you for the code. I agree that when I check the values per the columns the numbers are in agreement. However, if I run the conditioning code as posted, using "myMargin22" as the dynamic parameter, the table on the left hand side is prodcued. I switch my code to use "myMargin22_foreign" the table on the right is produced. Each have the same number of trades but the exposure is different because with "myMargin22" the margin used in the formula is always equal to 1 whereas in the right table margin varies between 1 and 2.

I will review the link you pointed to as well.

Thank you for the code, advice & your patience.

Mike

Please post up your current full code.

TrendSurfer,

I cannot figure out why myMargin22 and myMargin22_foreign yield different results. I tried in a very simple script, no CBT, and the results with either myMargin22 variables is identical. However, when I try with the intended script, posted below, I get different results with myMargin22 defaulting to always using "1" and myMargin22_foreign dynamically changing from 1 to 2 correctly.

Thanks in advance for your help!

Mike

SetChartOptions(0,chartShowArrows|chartShowDates);
_N(Title = StrFormat("{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ));
Plot( C, "Close", ParamColor("Color", colorDefault ), styleNoTitle | ParamStyle("Style") | GetPriceStyle() ); 

ApplyStop( stopTypeNBar, stopModeBars, 5 );

_SECTION_BEGIN("Entry / Exit");
UseShort = ParamToggle("Allow Short", "No|Yes", 0);
EntryOption = ParamList("Entry Price", "Close of Current Bar|Open of Next Bar|Close of Next Bar|Average OHLC of Next Bar");
UseSL = ParamToggle("Use Stop Loss", "No|Yes", 1);
UseTP = ParamToggle("Use Profit Target", "No|Yes", 0);
SLOnLostOption = ParamList("SL On Lost Option", "Keep SL|Reset SL", 1);
SLAdjustmentFactor = Param("SL Adjustment Factor", 1.0, 0.1, 100, 0.1);
MaxHoldingPeriod = Param("Max Holding Period", 100, 1, 100);
ProfitTargetPct = Param("Profit Target %", 40, 0.1, 100, 0.1)/100;
StopLossPct = Param("Stop Loss %", 1.5, 0.1, 100, 0.1)/100;
SlippagePct = Param("Slippage %", 0.0, -100, 100, 0.1)/100;
SLCount = Param("SL Count", 0, 0, 100, 1);
AllocMethod = ParamList("Allocation Method", "Equal|Maximum", 1);
MinPosCount = Param("Min # of Positions", 1, 1, 100, 1);
SymbolCount = Param("# of Symbols", 1, 1, 1000, 1);
MyMargin = Param("Margin ##:1", 2.0, 0, 10, 1);

_SECTION_BEGIN("MA Cross Strategy");

function Trace(tt, str) {
	_TRACE(DateTimeToStr(tt)+" "+str);
}

function XMA(period) {
	res = IIf(AvgType == "SMA", MA(O, period), EMA(O, period));
	
	return res;
}
_SECTION_END();

//Expression 1
SPY_close = Foreign("SPY", "C");
SPY_trendup_foreign = SPY_close > MA(SPY_close, 2);
myMargin22_foreign = IIf(SPY_trendup_foreign, 2, 1);

//Expression 2
SPY_trendup = close > MA(close, 2);//clicking on SPY in watchlist & have set to "Current"
myMargin22 = IIf(SPY_trendup, 2, 1);


//assume timeframe = Daily
symbol = Name();
dt = DateTime();
dn = DateNum();
dow = DayOfWeek();
mn = Month();

newMonth = mn != Ref(mn, -1);

SetCustomBacktestProc("");

SetOption("AccountMargin",100/MyMargin);

if( Status( "action" ) == actionPortfolio ) {

	/*
	if ( GetOption( "ApplyTo" ) == 2 )  { 
		 wlnum = GetOption( "FilterIncludeWatchlist" ); 
		 List = CategoryGetSymbols( categoryWatchlist, wlnum ) ; 
	} 
	else if ( GetOption( "ApplyTo" ) == 0 ) { 
		 List = CategoryGetSymbols( categoryAll, 0 ); 
	} 
	else { 
		 List = Name();
	}

	symbolCount = StrCount(List, ",")+1;
	*/	

	_TRACE("Symbol Count "+symbolCount);

    bo = GetBacktesterObject();
    bo.PreProcess();
		
    for( i = 0; i < BarCount; i++ ) {
    bo.HandleStops(i);
    //MR   
LongList = "";
ShortList = "";

//_TRACE( "[AB] " +DateTimeToStr( dt[ i ] ) );
//bo.RawTextOutput( DateTimeToStr( dt[ i ] ) );

		if (GetOption("PortfolioReportMode") != 0) { 
			bo.RawTextOutput( DateTimeToStr( dt[ i ] ) );       
		}
		bo.UpdateStats(i, 0);
		posCount = 0;
		for (sig = bo.GetFirstSignal(i); sig; sig = bo.GetNextSignal(i)) {
			if (sig.IsEntry()) {
				posCount++;
			}
			else if (sig.IsExit()) {
				bo.ExitTrade(i, sig.Symbol, sig.Price);
			}
		}

		bo.UpdateStats(i, 1);

	
		if (AllocMethod == "Equal") {
			posSize = (bo.Cash *MyMargin22[i]) / symbolCount;
		}
		else {
			posSize = (bo.Cash *MyMargin22[i]) / Max(MinPosCount, posCount);
		}

		for (sig = bo.GetFirstSignal(i); sig; sig = bo.GetNextSignal(i)) {
			if (sig.IsEntry()) {
				bo.EnterTrade(i, sig.Symbol, sig.IsLong(), sig.Price, posSize);
			}
		}
		bo.UpdateStats(i, 2);
    } 
    bo.PostProcess();
}

Startperiod= dow==5;

ShortTerm=Close;
LongTerm = Ref(Close,-20);


IsUp = ShortTerm > LongTerm;
IsDown = ShortTerm < LongTerm;

Buy1 = (ShortTerm-LongTerm)/Longterm *100 > 0.50 && StartPeriod && ShortTerm >MA(Close,200); //ShortTerm > LongTerm && StartPeriod;//ShortTerm > LongTerm && StartPeriod;
Short1 = ShortTerm < LongTerm && StartPeriod;

Buy1 = IIf(EntryOption == "Close of Current Bar", Buy1, Ref(Buy1, -1));
Short1 = IIf(EntryOption == "Close of Current Bar", Short1, Ref(Short1, -1));
BuyPrice = IIf(EntryOption == "Open of Next Bar", O,
			IIf(EntryOption == "Average OHLC of Next Bar", (O+H+L+C)/4, C));
BuySL = BuyPrice*(1 - StopLossPct);
BuyTP = BuyPrice*(1 + ProfitTargetPct);

ShortPrice = BuyPrice;
ShortSL = ShortPrice*(1 + StopLossPct);
ShortTP = ShortPrice*(1 - ProfitTargetPct);
			
Buy = Sell = Short = Cover = 0;

inTrade = 0; //Buy = 1, Short = 2
SL=TP=0;
TradePeriod=0;
BuyCount = ShortCount = 0;
ExitCode = 1; //1 = By PT/SL, 2 = By End of Holding Period
LastProfit = 0;
FirstTrade = true;
EntryPrice = 0;
SLBuffer = TPBuffer = Null;
NextTradePeriod=0;
for (i=0; i<BarCount; i++) {
	if (StartPeriod[i]) {
		TradePeriod++;
	}

	if (inTrade != 0) {		
		TPBuffer[i] = TP;
		SLBuffer[i] = SL;		
		if (inTrade == 1) { //Long
			if (L[i] <= SL && UseSL) {
				Sell[i] = 1;
				inTrade = 0;
				SellPrice[i] = IIf(O[i] <= SL, O[i], SL);
				ExitCode = 1;
				NextTradePeriod = TradePeriod+SLCount;
			}
			else if (H[i] >= TP && UseTP) {
				Sell[i] = 1;
				inTrade = 0;
				SellPrice[i] = IIf(O[i] >= TP, O[i], TP);
				ExitCode = 1;
			}
			else if (StartPeriod[i]) { //reached start of next period / end of current period
			//else if (newWeek[i]) { //reached start of next period / end of current period
				Sell[i] = 1;
				inTrade = 0;
				SellPrice[i] = C[i];
				ExitCode = 2;
			}
			else if (BuyCount > MaxHoldingPeriod) { //3d. Exit at opposite signal
				if (IsDown[i]) {
					Sell[i] = 1;
					inTrade = 0;
					SellPrice[i] = C[i];
					BuyCount = 0;
				}
			}
			
			if (inTrade == 0) {
				SellPrice[i] = (1+SlippagePct)*SellPrice[i];
				LastProfit = SellPrice[i] - EntryPrice;
			}
		}
		else { //Short
			if (H[i] >= SL && UseSL) {
				Cover[i] = 1;
				inTrade = 0;
				CoverPrice[i] = IIf(O[i] >= SL, O[i], SL);
				ExitCode = 1;
				NextTradePeriod = TradePeriod+SLCount;
			}
			else if (L[i] <= TP && UseTP) {
				Cover[i] = 1;
				inTrade = 0;
				CoverPrice[i] = IIf(O[i] <= TP, O[i], TP);				
				ExitCode = 1;
			}
			else if (StartPeriod[i]) {
				Cover[i] = 1;
				inTrade = 0;
				CoverPrice[i] = C[i];
				ExitCode = 2;
			}
			else if (ShortCount > MaxHoldingPeriod) { //3d. Exit at opposite signal
				if (IsUp[i]) {
					Cover[i] = 1;
					inTrade = 0;
					CoverPrice[i] = C[i];
					ShortCount = 0;
				}
			}
			if (inTrade == 0) {
				CoverPrice[i] = (1-SlippagePct)*CoverPrice[i];
				LastProfit = EntryPrice[i] - CoverPrice[i];
			}			
		}				
	}
	
	if (inTrade == 0 && TradePeriod > NextTradePeriod) {
		//check buy
		if (Buy1[i]) {
			Buy[i] = 1;
			inTrade = 1;
			TP = BuyTP[i];
			//SLOnLostOption = ParamList("SL On Lost Option", "Keep SL|Reset SL", 0);
			SL = IIf(ExitCode == 2 && LastProfit < 0 && SLOnLostOption == "Keep SL", SL = SL + SL*(SLAdjustmentFactor - 1), BuySL[i]);
			TPBuffer[i] = TP;
			SLBuffer[i] = SL;
			BuyCount++;
			ShortCount=0;
			FirstTrade = False;
			EntryPrice = BuyPrice[i];
		}
		else if (Short1[i] && UseShort) {
			Short[i] = 1;
			inTrade = 2;
			TP = ShortTP[i];
			SL = IIf(ExitCode == 2 && LastProfit < 0 && SLOnLostOption == "Keep SL", SL = SL - SL*(SLAdjustmentFactor - 1), ShortSL[i]);
			TPBuffer[i] = TP;
			SLBuffer[i] = SL;			
			ShortCount++;
			BuyCount=0;
			FirstTrade = False;
			EntryPrice = ShortPrice[i];
		}
		else {
			BuyCount=0;
			ShortCount=0;
		}
	}
}

bgColor = IIf(StartPeriod, colorLime, colorDefault);

PlotShapes(IIf(StartPeriod, shapeSquare, shapeNone), colorWhite, 0, H, 0);
PlotShapes(IIf(StartPeriod, shapeSquare, shapeNone), colorWhite, 0, L, 0);

PlotShapes(IIf(Buy, shapeUpArrow, shapeNone), colorLime, 0, L, -24);
PlotShapes(IIf(Short, shapeDownArrow, shapeNone), colorRed, 0, H, -24);

PlotShapes(IIf(Sell, shapeCircle, shapeNone), colorLime, 0, SellPrice, 0);
PlotShapes(IIf(Cover, shapeCircle, shapeNone), colorRed, 0, CoverPrice, 0);

Plot(ShortTerm, "Short Term", colorYellow);
Plot(LongTerm, "Long Term", colorLightBlue);
if (UseSL) {
	Plot(SLBuffer, "Stop Loss", colorRed, styleDashed);
}
if (UseTP) {
	Plot(TPBuffer, "Profit Target", colorRed, styleDashed);
}

Filter = 1;

AddColumn(StartPeriod, "Period", 1.0);
AddColumn(Buy, "Buy", 1.0);
AddColumn(Short, "Short", 1.0);

AddColumn(Close, "Close", 1.0);
AddColumn(MA(Close, 2), "MA(Close, 2)", 1.0);
AddColumn(SPY_trendup_foreign, "SPY_trendup_foreign", 1.0);
AddColumn(myMargin22_foreign, "myMargin22_foreign", 1.0);
AddColumn(SPY_trendup, "SPY_trendup", 1.0);
AddColumn(myMargin22, "myMargin22", 1.0);

_SECTION_END();


type or paste code here

Your code needs some changes and tidy up.

I would just use as previously suggested for your dynamic position sizing.

If you want to stay with using the CBT to do your dynamic position sizing then you could use the below which is a slight modification of this method positionsize-in-cbt.

// Use with static 'SetOption("AccountMargin",100/MyMargin);'

SPY_close = Foreign("SPY", "C");
SPY_trendup_foreign = SPY_close > MA(SPY_close, 2);
myMargin_dynamic = IIf(SPY_trendup_foreign, 1, 2);

PositionSize = Ref(Close, -1) * myMargin_dynamic;  // Use instead of 'SetPositionSize(..., spsPercentOfEquity);

SetCustomBacktestProc("");

if (Status("action") == actionPortfolio) 
{
    bo = GetBacktesterObject();
    bo.PreProcess();
    
    for (i = 0; i < BarCount; i++)
    {
        for (sig = bo.GetFirstSignal(i); sig; sig = bo.GetNextSignal(i))
        {	
			if (sig.IsEntry())
			{
				CashAvailable = bo.Cash / (MaxPos - bo.GetOpenPosQty());
				SharesNeed = floor(CashAvailable / sig.PosSize); // at this moment PosSize really holds our prev close !
				sig.PosSize = -2000 - SharesNeed; // calc actual pos size !
			}
        }	
        bo.ProcessTradeSignals(i);
    }
    bo.PostProcess();
}

Hi Trendsurfer,

Thank you! For my purposes, I will work with the second example.

Thanks,

Mike

This topic was automatically closed 100 days after the last reply. New replies are no longer allowed.