Variable updates previous values (Expected behavior, need suggestions)

Hi experts,

Need some assistance here.

I am using Options and trying to gather some value based on the volume and open interest.

for ( k = -30; k <=30 ; k++)
{
ATMS = VarGet("Strike"+BarIndex());
SelStrike = ATMS + (k * strikeinterval);
CE_symbol = symbol + VarGetText("Expiry") + StrFormat("%.0f",SelStrike) + CE;
//Getting data for the symbol above
// Making required calculations
//Getting final values
}

In the above sample code, I am accessing the various option symbols available one by one and getting the values.

I am then using this information in a for loop to calculate and take positions accordingly:

for(i=1;i<BarCount;i++)
{
// Using the data above to update values 
}

My issue is as follows:

Since I am looking at + or - 30 symbols from the current price (in terms of strikes), whenever there is a change in the symbols for which the loopup is done (Say for example the ATMS value changes by 500, then the symbols also change for which I am doing a look up) - this leads to a change in overall values.

Because the for loop is calculating everything from the beginning, the variables change and my end result also changes.

So within the for loop:

If the CE strike value was, say 30000 - because it is re-calculated at times, it changes to 30100.

While this is fine during explorations, it is hurting me during live execution strategy planning. Any suggestions on how I can avoid it.

My requirement here would be that the values arrived from the first loop (k based loop) only change the future values and not the older values due to which my overall result does not hurt.

I think I am doing some basic stuff wrong and would really appreciate any help on this.

Thanks
Siddhant Kankani

Hi,

Any suggestions on how I can tackle this ?

Thanks

You can't use BarIndex() like this.

While setting ATMS, it is being set within a for loop:

for(i=0;i<BarCount;i++)
{
//Some code to calculate Strike
VarSet("Strike"+i,Strike);
}

If not for Barindex, how else can I retrieve the value. Barindex here is only the name of the variable.

Thanks
Siddhant Kankani

BarIndex() returns an array. You need to VarGet the same way you did VarSet, ie. iterate using loop.

If Strike is a numeric value, why aren't you just doing something like this?

StrikeArray = 0;
for(i=0;i<BarCount;i++)
{
   //Some code to calculate Strike
   StrikeArray[i] = Strike;
}

Similarly, your VarGet can just be replaced with:

StrikeArray[i]
2 Likes

As @mradtke said - first you need to read Understanding how AFL works , then use recommended resources to learn the basics and then use variables directly without VarSet/VarGet functions.

Thanks @mradtke & @Tomasz,

Will try the changes and update the thread on the progress.

Thanks again,
Siddhant Kankani

Hi @mradtke

I have removed all instances of VarSet / VarGet and replaced them with normal variables.

The scenario however still persists:

From the basic debugging that I have done, I understand this is because:

  1. My OI logic is calculated by looking at + or - 50 strikes.
  2. Eg, in my case, if Banknifty(one of the instruments I trade) is trading at 30000 - then it looks at the next 50 strikes and previous 50 strikes to come to the OI logic.
  3. Now, if Banknifty goes up by 500 points, then the 50 strikes that it looked previously changes.

I think because I am doing a lot of my calculations inside a for loop, the previous values that are carried forward are also updated based on the new OI values.

Example of the scenario below:

Please see the future units pos in the image below [0.45] (in the box on the left)
image

The only thing done between this bar and the next in the code is (inside the for loop):

future_units_pos[i] = future_units_pos[i-1];

Next bar: [Please see the value of Future Units pos changes to 0.42]
image

Now, if I change the OI lookup value from 50 strikes to 100 strikes: -100 to +100 - the issue is resolved in this case.

In some cases, the number of strikes are added dynamically (when markets move rapidly on either side) and hence just increasing the number wont be a permanent solution in live markets.

Would love your suggestion on how I can tackle this.

Please let me know if any other information would be required on the same.

Thanks again,
Siddhant Kankani

Sorry, I don't understand what the problem is, and you haven't posted your full code so it's unlikely that anyone will be able to guess what your error is.

I suggest you read this post: How do I debug my formula? to help you better understand what your code is doing and where the problem originates. If you are still not able to figure out a solution, then provide more details here as suggested in the post How to ask a good question

2 Likes

Hi @mradtke

Trying to put the details in a more clearer manner here:

Here is a sample code with which I am able to reproduce the issue:

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

symbol ="BANKNIFTY";
strikeinterval = 100;
offset = 0;
Closing = Foreign("BANKNIFTY-I.NFO","Close");
tn = TimeNum();
CE = "CE.NFO";
PE = "PE.NFO";

for(i=1;i<BarCount;i++)
//for (i = FirstBar; i < LastBar; i++)
{
ltp = Closing[i];

iPE = ltp - (ltp%strikeinterval);   //nearest strike price   11536-36 =  11500 , 11536 is the spot price
iCE = ltp - (ltp%strikeinterval);

iPE = iPE - (offset*strikeinterval);
iCE = iCE + (offset*strikeinterval);


if(( ltp % strikeinterval) > (strikeinterval/2))   //11525 reminder = 36 > 25,    CE = 11550, PE = 11500    11502 , CE = 11500, PE = 11500
{

iCE = ltp - (ltp%strikeinterval)+strikeinterval;
iPE= ltp - (ltp%strikeinterval)+(strikeinterval);

iPE = iPE - (offset*strikeinterval);
iCE = iCE + (offset*strikeinterval);

}

strike[i] = iPE;

}
expiry = "01APR21";

//expiry = expiry_string;
ce_max_strike = pe_max_strike = 0;
//CE_max_strike = 0;
CE_max_OI = 0;
//PE_max_strike = 0;
PE_max_OI = 0;

CE_OI = PE_OI = 0;


for ( k = -50 ; k <=50 ; k++)
{
ATMS = Strike;
SelStrike = ATMS + (k * strikeinterval);
//Building the CE symbol
CE_symbol = symbol + expiry + StrFormat("%.0f",SelStrike) + CE;
//Getting OI and price of the symbol
CE_OI_temp_arr = Foreign(CE_symbol,"I");
CE_Price_arr = Foreign(CE_symbol,"C");
// Getting start of day OI and calculating change
CE_oi_temp_day_start =  IIf(!IsNull(CE_OI_temp_arr),ValueWhen(TimeNum() == 092500,CE_oi_temp_arr),0);
CE_Change_OI = IIf(!IsNull(CE_OI_temp_arr),CE_OI_temp_arr - CE_oi_temp_day_start,Null);
CE_OI = IIf ( !IsNull(CE_Change_OI), CE_OI + CE_Change_OI, CE_OI);


//Same for Put side
PE_symbol = symbol + expiry + StrFormat("%.0f",SelStrike) + PE;
PE_OI_temp_arr = Foreign(PE_symbol,"I");
PE_oi_temp_day_start =  IIf(!IsNull(PE_OI_temp_arr),ValueWhen(TimeNum() == 092500,PE_oi_temp_arr),0);
PE_Price_arr = Foreign(PE_symbol,"C");
PE_Change_OI = IIf(!IsNull(PE_OI_temp_arr),(PE_OI_temp_arr - PE_oi_temp_day_start),Null);
PE_OI = iif(!IsNull(PE_Change_OI),PE_OI + PE_Change_OI,PE_OI);

PE_max_OI = IIf ( PE_max_OI > PE_Change_OI OR IsNull(PE_Change_OI), PE_max_OI, PE_Change_OI);

}

PE_OI_temp = IIf( PE_OI < 0 AND CE_OI < 0, abs(CE_OI), PE_OI);
CE_OI_temp = IIf ( PE_OI < 0 AND CE_OI < 0, abs(PE_OI), CE_OI);


printf("\n CE OI temp:" +StrFormat("%.0f",CE_OI_temp));
printf("\n PE OI temp:" +StrFormat("%.0f",PE_OI_temp));

multiplier = IIf ( PE_OI_temp > CE_OI_temp, abs(1 / PE_OI_temp), abs(1 / CE_OI_temp));

//Calculation of units

CE_units = IIf ( CE_OI_temp <= 0 AND PE_OI_temp >= 0 , 0 ,
								IIf ( CE_OI_temp >= 0 AND PE_OI_temp <= 0 , 1 , 
								IIf (PE_OI_temp > CE_OI_temp, CE_OI_temp * multiplier, 1)));


PE_units = IIf ( PE_OI_temp <= 0 AND CE_OI_temp >= 0 , 0 ,
								IIf ( PE_OI_temp >= 0 AND CE_OI_temp <= 0 , 1 , 
								IIf (CE_OI_temp > PE_OI_temp, PE_OI_temp * multiplier, 1)));

future_units = IIf ( CE_units == PE_units, 0,
				IIf (CE_units > PE_units, -1 * (CE_units - PE_units), 1 * (PE_units - CE_units)));
				
future_units_pos = 0;

for(i=1;i<BarCount;i++)
{
	future_units_pos[i] = future_units_pos[i-1];
	if (tn[i] == 151500)
	{
		future_units_pos[i] = future_units[i];
	}
}
	
GfxSetOverlayMode(0);
GfxSetBkMode(0);
GfxSelectFont("Tahoma",10,400);
GfxSelectSolidBrush(colorLightGrey);
GfxRectangle(20,330,320,770);

GfxTextOut("Future Units Pos :"+StrFormat("%.2f",future_units_pos),28,410);

If you look at the code, the first part of the code (First if loop) is calculating the strike value.
The second loop is running through multiple different symbols to get some value based on Open interest.
The third loop is just setting the calculated unit value to a variable at a specified time and the value should remain the same till the next day as per the condition [The actual program has a lot more conditions here due to which I am using the for loop]

future_units_pos[i] = future_units_pos[i-1];
	if (tn[i] == 151500)
	{
		future_units_pos[i] = future_units[i];
	}

Taking one instance, value of Future position at 15:20 hours on 25/3/2020 is 0.00

image

When I move two bars out, the value changes to -0.04.
image

If I change the second for loop (OI calculation loop) to:

for ( k = -100 ; k <=100 ; k++)

The value does not change from moving from one bar to another.

By debugging, I have come to a point where I understand that :

SelStrike = ATMS + (k * strikeinterval);
//Building the CE symbol
CE_symbol = symbol + expiry + StrFormat("%.0f",SelStrike) + CE;

The CE symbol differs at each point based on the current price of the underlying instrument and hence this issue comes up.

How do I avoid this scenario?
I am presuming it is because the for loop ( i = 1 to Barcount) is running everytime and hence new calculations coming up. Can I probably change the loop to only run the last couple of values / can I have someway of storing some of the variables so that it doesnt change?

Hope my query was clear this time around.
Look forward to your suggestions.

Thanks
Siddhant Kankani

To get better understanding of what is happening in your code and how functions work, use advice given here: How do I debug my formula?
So once again: run your code step by step under debugger so you understand what is happening in your code.

The fundamental thing is that you understand YOURSELF what you wrote, not to copy-paste ready solutions.

And simplify. You need to divide your program into SMALL possibly independent parts. To do so you have to do thinking before you start to type any code. Divide the PROBLEM you are having into smallest possible "subtasks". Use advice from @KeithMcC post How do I debug my formula? - #11 by KeithMcC