Combining multiple strategies on same symbol into one code

Hi there,

assuming you have ten SPY strategies which you want to backtest all together, and since only 3-5 should be invested at the same time you need to do it in one strategy. I already know how to code the different entries and exits (using switch case expressions), how can I achieve that multiple positions in the same symbol are being opened? I guess I need to do some scaling in and scaling out, alreqdy checked the docs, but so far I didn't succeed. Is anybody doing something similar amd can share some sample code? Any hints are highly appreciated!

Thanks,
M

1 Like

I don't know if this helps @matzbanni, as I think that my setup is a bit different than yours, but I have a separate window/chart for each system. It makes it easer for me to generally manage, evaluate performance and keeps each system on a separate thread for speed. The code that manages the positions and places the orders are kept in include files and I make ample use of static variables throughout the code.

1 Like

Unfortunately not, I'm talkin about backtesting e.g. 10 systems, when only 4 are allowed to br invested simultaneously.

1 Like

Off the top of my head, if I had to keep all the code in one window, I'd probably just layer each system in separate procedures and then just toggle the ones on/off with code above it that I wanted to be active at the time. Then below that would be your position management and then broker execution code.

If that does not help can you be very specific @matzbanni as to what areas you are struggling with? Is it just the logic of how to put everything together?

I'll post some sample code later as soon as I'm in front of my laptop in order to illustrate my problem.

1 Like

I tried it like this, see below. However, with this approach only buy signals are used when I'm not in a position (but I want to be in multiple positions on the same symbol though). I guess I need to switch that to some sort of counter, which checks the current open positions etc. Not as easy as I thought it'll be to be honest.

// BACKTESTER SETTINGS

SetOption("InitialEquity",100000);
SetOption("AllowPositionShrinking", True);
SetOption("maxopenpositions", 100);
SetBacktestMode( backtestRegularRaw);
BuyPrice = SellPrice = Close;
RoundLotSize = 1;
Buy = Sell = Short = Cover = 0;

Buy21 = Cross(MA(C, 50), MA(C, 200));
Buy22 = Cross(MA(C, 20), MA(C, 50));
Buy23 = Cross(MA(C, 10), MA(C, 20));

Sell21 = Cross(MA(C, 200), MA(C, 50));
Sell22 = Cross(MA(C, 50), MA(C, 20));
Sell23 = Cross(MA(C, 20), MA(C, 10));


Plot(Buy21, "T1", colorYellow, styleThick );
Plot(Buy22, "T2", colorBlue, styleThick );
Plot(Buy23, "T3", colorBrown, styleThick );

InTrade = 0;
Buy = 0;
Sell = 0;

for( i = 0; i < BarCount; i++ )
{
	switch( InTrade )
	{
		case 0: // not in trade
			if( Buy21[ i ] ) 
			{
				Buy[i] = sigScaleIn;
				InTrade = 21;
			}
			else
			if( Buy22[ i ] )
			{
				Buy[i] = sigScaleIn;
				InTrade = 22;
			}
			else
			if( Buy23[ i ] )
			{
				Buy[i] = sigScaleIn;
				InTrade = 23;
			}
			
			break;
			
		case 21:
			if( Sell21[ i ] ) 
			{
				Buy[i] = sigScaleOut;
				InTrade = 0; 
			}
			break;
			
		case 22:
			if( Sell22[ i ] ) 
			{
				Buy[i] = sigScaleOut;
				InTrade = 0; 
			}
			break;

		case 23:
			if( Sell23[ i ] ) 
			{
				Buy[i] = sigScaleOut;
				InTrade = 0;  
			}
			break;
	}
}

SetPositionSize( 50, spsPercentOfEquity );
SetPositionSize( 100, spsPercentOfPosition * ( Buy == sigScaleOut ) );

i mistakenly assumed you were trading futures so I made an example for futures. The principle is the same for stocks. Maybe later I will try to add an example for stocks (SPY). You can solve this in multiple ways. Below is an example for futures where for system21 I trade 3 contracts, system22 2 contracts and system 23 1 contract. You can use the cursor on the chart to see in the Title what the positions are doing

// BACKTESTER SETTINGS
SetTradeDelays( 0, 0, 0, 0 );
SetOption( "FuturesMode", True );
SetOption( "PriceBoundChecking", False );
SetOption( "AllowSameBarExit", True );
SetOption( "CommissionMode", 3 );
SetOption( "CommissionAmount", 2.5 );
BuyPrice = SellPrice = Close;
Buy = Sell = 0;
NumContracts21 = 3;
NumContracts22 = 2;
NumContracts23 = 1;

Buy21 = Cross( MA( C, 50 ), MA( C, 200 ) );
Buy22 = Cross( MA( C, 20 ), MA( C, 50 ) );
Buy23 = Cross( MA( C, 10 ), MA( C, 20 ) );

Sell21 = Cross( MA( C, 200 ), MA( C, 50 ) );
Sell22 = Cross( MA( C, 50 ), MA( C, 20 ) );
Sell23 = Cross( MA( C, 20 ), MA( C, 10 ) );

// combining the systems
Buy21 = ExRem( Buy21, Sell21 );
Sell21 = ExRem( Sell21, Buy21 );
Buy22 = ExRem( Buy22, Sell22 );
Sell22 = ExRem( Sell22, Buy22 );
Buy23 = ExRem( Buy23, Sell23 );
Sell23 = ExRem( Sell23, Buy23 );

inBuy21 = Nz( Flip( Buy21, Sell21 ) );
inBuy22 = Nz( Flip( Buy22, Sell22 ) );
inBuy23 = Nz( Flip( Buy23, Sell23 ) );

totalPositions = IIf( inBuy21, 1, 0 ) * NumContracts21 +
                 IIf( inBuy22, 1, 0 ) * NumContracts22 +
                 IIf( inBuy23, 1, 0 ) * NumContracts23;
actionAtBar = totalPositions - Ref( totalPositions, -1 );

Buy = IIf( actionAtBar >= 1 AND totalPositions >= 1 AND Ref( totalPositions, -1 ) == 0, 1, 0 );
Buy = IIf( actionAtBar >= 1 AND totalPositions >= 1 AND Ref( totalPositions, -1 ) >= 1, sigScaleIn, Buy );
Buy = IIf( actionAtBar <= -1 AND totalPositions >= 1, sigScaleOut, Buy );
Sell = IIf( actionAtBar <= -1 AND totalPositions == 0, 1, 0 );

SetChartBkColor( ColorRGB( 0, 0, 0 ) );
SetChartOptions( 0, chartShowArrows | chartShowDates );
Plot( C, "C", colorWhite, styleCandle, Null, Null, 0, 0, 1 );
Plot( MA( C, 10 ), "Ma10", colorYellow, styleLine | styleNoRescale, Null, Null, 0, 0, 1 );
Plot( MA( C, 20 ), "Ma20", colorViolet, styleLine | styleNoRescale, Null, Null, 0, 0, 1 );
Plot( MA( C, 50 ), "Ma50", colorPaleTurquoise, styleLine | styleNoRescale, Null, Null, 0, 0, 1 );
Plot( MA( C, 200 ), "Ma200", colorBlue, styleLine | styleNoRescale, Null, Null, 0, 0, 1 );
Plot( totalPositions, "total positions", colorGold, styleLine | styleOwnScale | styleStaircase, Null, Null, 0, 0, 1 );

Title =
    "actionAtBar: " + actionAtBar +
    EncodeColor( colorGold ) + "\n totalPositions: " + totalPositions + EncodeColor( colorWhite ) +
    "\n Ref( totalPositions, -1 ): " + Ref( totalPositions, -1 ) +
    "\n Buy: " + Buy +
    "\n Sell: " + Sell +
    "\n Buy21: " + Buy21 +
    "\n Buy22: " + Buy22 +
    "\n Buy23: " + Buy23 +
    "\n Sell21: " + Sell21 +
    "\n Sell22: " + Sell22 +
    "\n Sell23: " + Sell23;

PlotShapes( IIf( Buy == 1, shapeUpArrow, shapeNone ), colorDarkGreen, 0, L, -20 );
PlotShapes( IIf( Buy == 1, shapeSmallCircle, shapeNone ), colorWhite, 0, BuyPrice, 0 );
PlotShapes( IIf( Buy == sigScaleIn, shapeUpArrow, shapeNone ), colorBrightGreen, 0, L, -20 );
PlotShapes( IIf( Buy == sigScaleIn, shapeSmallCircle, shapeNone ), colorWhite, 0, BuyPrice, 0 );
PlotShapes( IIf( Buy == sigScaleOut, shapeDownArrow, shapeNone ), colorGold, 0, H, -20 );
PlotShapes( IIf( Buy == sigScaleOut, shapeSmallCircle, shapeNone ), colorWhite, 0, BuyPrice, 0 );
PlotShapes( IIf( Sell, shapeDownArrow, shapeNone ), colorRed, 0, H, -20 );
PlotShapes( IIf( Sell, shapeSmallCircle, shapeNone ), colorWhite, 0, SellPrice, 0 );

PlotShapes( IIf( Buy21, shapeUpTriangle, shapeNone ), colorBrightGreen, 0, L, -40 );
PlotShapes( IIf( Sell21, shapeDownTriangle, shapeNone ), colorBrightGreen, 0, H, -40 );
PlotShapes( IIf( Buy22, shapeUpTriangle, shapeNone ), colorYellow, 0, L, -40 );
PlotShapes( IIf( Sell22, shapeDownTriangle, shapeNone ), colorYellow, 0, H, -40 );
PlotShapes( IIf( Buy23, shapeUpTriangle, shapeNone ), colorAqua, 0, L, -40 );
PlotShapes( IIf( Sell23, shapeDownTriangle, shapeNone ), colorAqua, 0, H, -40 );

SetPositionSize( abs( actionAtBar ), IIf( Buy OR Sell, spsShares, spsNoChange ) );
5 Likes

here is for SPY. Instead of contract I use percentOfEquity. Did a quick test, seems OK but no guarantees. So system21 buys 50% of equity, system22 30% and sysmtem23 20%.

If you want to see all details of the backtest you have to set the report settings to detailed log.

// BACKTESTER SETTINGS
SetTradeDelays( 0, 0, 0, 0 );
SetOption("InitialEquity",100000);
SetOption( "PriceBoundChecking", False );
SetOption( "CommissionMode", 3 );
SetOption( "CommissionAmount", 0.005 );
RoundLotSize = 1;
TickSize = 0.01;
MarginDeposit = 5000;
PointValue = 1;
BuyPrice = SellPrice = Close;
Buy = Sell = 0;

PercentOfEquity21 = 50;
PercentOfEquity22 = 30;
PercentOfEquity23 = 20;

Buy21 = Cross( MA( C, 50 ), MA( C, 200 ) );
Buy22 = Cross( MA( C, 20 ), MA( C, 50 ) );
Buy23 = Cross( MA( C, 10 ), MA( C, 20 ) );

Sell21 = Cross( MA( C, 200 ), MA( C, 50 ) );
Sell22 = Cross( MA( C, 50 ), MA( C, 20 ) );
Sell23 = Cross( MA( C, 20 ), MA( C, 10 ) );

// combining the systems
Buy21 = ExRem( Buy21, Sell21 );
Sell21 = ExRem( Sell21, Buy21 );
Buy22 = ExRem( Buy22, Sell22 );
Sell22 = ExRem( Sell22, Buy22 );
Buy23 = ExRem( Buy23, Sell23 );
Sell23 = ExRem( Sell23, Buy23 );

inBuy21 = Nz( Flip( Buy21, Sell21 ) );
inBuy22 = Nz( Flip( Buy22, Sell22 ) );
inBuy23 = Nz( Flip( Buy23, Sell23 ) );

totalPositions = IIf( inBuy21, 1, 0 ) * PercentOfEquity21 +
                 IIf( inBuy22, 1, 0 ) * PercentOfEquity22 +
                 IIf( inBuy23, 1, 0 ) * PercentOfEquity23;
actionAtBar = totalPositions - Ref( totalPositions, -1 );

Buy = IIf( actionAtBar >= 1 AND totalPositions >= 1 AND Ref( totalPositions, -1 ) == 0, 1, 0 );
Buy = IIf( actionAtBar >= 1 AND totalPositions >= 1 AND Ref( totalPositions, -1 ) >= 1, sigScaleIn, Buy );
Buy = IIf( actionAtBar <= -1 AND totalPositions >= 1, sigScaleOut, Buy );
Sell = IIf( actionAtBar <= -1 AND totalPositions == 0, 1, 0 );

// remove excess signals at start (this is just for display purposes)
Sell21 = IIf( Sell21 AND !( Buy OR Sell ), 0, Sell21 );
Sell22 = IIf( Sell22 AND !( Buy OR Sell ), 0, Sell22 );
Sell23 = IIf( Sell23 AND !( Buy OR Sell ), 0, Sell23 );

SetChartBkColor( ColorRGB( 0, 0, 0 ) );
SetChartOptions( 0, chartShowArrows | chartShowDates );
Plot( C, "C", colorWhite, styleCandle, Null, Null, 0, 0, 1 );
Plot( MA( C, 10 ), "Ma10", colorYellow, styleLine | styleNoRescale, Null, Null, 0, 0, 1 );
Plot( MA( C, 20 ), "Ma20", colorViolet, styleLine | styleNoRescale, Null, Null, 0, 0, 1 );
Plot( MA( C, 50 ), "Ma50", colorPaleTurquoise, styleLine | styleNoRescale, Null, Null, 0, 0, 1 );
Plot( MA( C, 200 ), "Ma200", colorBlue, styleLine | styleNoRescale, Null, Null, 0, 0, 1 );
Plot( totalPositions, "total positions", colorGold, styleLine | styleOwnScale | styleStaircase, Null, Null, 0, 0, 1 );

Title =
    "actionAtBar: " + actionAtBar +
    EncodeColor( colorGold ) + "\n totalPositions (PercentOfEquity): " + totalPositions + EncodeColor( colorWhite ) +
    "\n Ref( totalPositions, -1 ): " + Ref( totalPositions, -1 ) +
    "\n Buy: " + Buy +
    "\n Sell: " + Sell +
    "\n Buy21: " + Buy21 +
    "\n Buy22: " + Buy22 +
    "\n Buy23: " + Buy23 +
    "\n Sell21: " + Sell21 +
    "\n Sell22: " + Sell22 +
    "\n Sell23: " + Sell23;

PlotShapes( IIf( Buy == 1, shapeUpArrow, shapeNone ), colorDarkGreen, 0, L, -20 );
PlotShapes( IIf( Buy == 1, shapeSmallCircle, shapeNone ), colorWhite, 0, BuyPrice, 0 );
PlotShapes( IIf( Buy == sigScaleIn, shapeUpArrow, shapeNone ), colorBrightGreen, 0, L, -20 );
PlotShapes( IIf( Buy == sigScaleIn, shapeSmallCircle, shapeNone ), colorWhite, 0, BuyPrice, 0 );
PlotShapes( IIf( Buy == sigScaleOut, shapeDownArrow, shapeNone ), colorGold, 0, H, -20 );
PlotShapes( IIf( Buy == sigScaleOut, shapeSmallCircle, shapeNone ), colorWhite, 0, BuyPrice, 0 );
PlotShapes( IIf( Sell, shapeDownArrow, shapeNone ), colorRed, 0, H, -20 );
PlotShapes( IIf( Sell, shapeSmallCircle, shapeNone ), colorWhite, 0, SellPrice, 0 );

PlotShapes( IIf( Buy21, shapeUpTriangle, shapeNone ), colorBrightGreen, 0, L, -40 );
PlotShapes( IIf( Sell21, shapeDownTriangle, shapeNone ), colorBrightGreen, 0, H, -40 );
PlotShapes( IIf( Buy22, shapeUpTriangle, shapeNone ), colorYellow, 0, L, -40 );
PlotShapes( IIf( Sell22, shapeDownTriangle, shapeNone ), colorYellow, 0, H, -40 );
PlotShapes( IIf( Buy23, shapeUpTriangle, shapeNone ), colorAqua, 0, L, -40 );
PlotShapes( IIf( Sell23, shapeDownTriangle, shapeNone ), colorAqua, 0, H, -40 );

SetPositionSize( abs( actionAtBar ), IIf( Buy OR Sell, spsPercentOfEquity, spsNoChange ) );
5 Likes

Wow, many thanks, I didn't expect a full blown solution! Will check it tomorrow asap, great end of the year :grin:

Best,
M

Great stuff, just tried it with my systems, works as expected. Final question, what if I want to limit the number of Scale Ins to two, meaning I do have three distinct strategies, but only want to take two signals at the same time, position size 50% each. Any hint on that?

Thanks in advance, M

that is a tough 1 I think to solve with arrays only. So if you for instance use:

PercentOfEquity21 = 50;
PercentOfEquity22 = 50;
PercentOfEquity23 = 50;

then you can limit the total "PercentOfEquity" to 100% using:

totalPositions = IIf( inBuy21, 1, 0 ) * PercentOfEquity21 +
                 IIf( inBuy22, 1, 0 ) * PercentOfEquity22 +
                 IIf( inBuy23, 1, 0 ) * PercentOfEquity23;
totalPositions = Min( 100, totalPositions ); // add this line
actionAtBar = totalPositions - Ref( totalPositions, -1 );

problem only is that it will start mixing the signals of the various systems.

So I am afraid you will need to use loops for that. Which is also not difficult. I just liked to solve it using arrays only. But will think about it a bit

here is a loop version. You will have to check if it is correct since I did not check if all is correct. I think in this case using a loop is the simplest way to go. Not sure if it can be solved with arrays only

Also for the backtest I think you will have to set Account margin to a lower value than 100 since else it often will not scale in if there are insufficient funds, see: account margin

// BACKTESTER SETTINGS
SetTradeDelays( 0, 0, 0, 0 );
SetOption( "InitialEquity", 100000 );
SetOption( "PriceBoundChecking", False );
SetOption( "CommissionMode", 3 );
SetOption( "CommissionAmount", 0.005 );
RoundLotSize = 1;
TickSize = 0.01;
MarginDeposit = 5000;
PointValue = 1;
BuyPrice = SellPrice = Close;
Buy = Sell = 0;

PercentOfEquity21 = 50;
PercentOfEquity22 = 50;
PercentOfEquity23 = 50;

Buy21 = Cross( MA( C, 50 ), MA( C, 200 ) );
Buy22 = Cross( MA( C, 20 ), MA( C, 50 ) );
Buy23 = Cross( MA( C, 10 ), MA( C, 20 ) );

Sell21 = Cross( MA( C, 200 ), MA( C, 50 ) );
Sell22 = Cross( MA( C, 50 ), MA( C, 20 ) );
Sell23 = Cross( MA( C, 20 ), MA( C, 10 ) );

// combining the systems
Buy21 = ExRem( Buy21, Sell21 );
Sell21 = ExRem( Sell21, Buy21 );
Buy22 = ExRem( Buy22, Sell22 );
Sell22 = ExRem( Sell22, Buy22 );
Buy23 = ExRem( Buy23, Sell23 );
Sell23 = ExRem( Sell23, Buy23 );

totalPositions = 0;
actionAtBar = 0;
totpos = 0;
maxtotpos = 100; // max 100%
inBuy21 = inBuy22 = inBuy23 = 0;

for( i = 1; i < BarCount; i++ )
{
    if( Buy21[i] AND totpos < maxtotpos )
    {
        if( totpos == 0 )
        {
            Buy[i] = 1;
        }
        else
            if( totpos > 0 )
            {
                Buy[i] = sigScaleIn;
            }

        totpos = totpos + PercentOfEquity21;
        actionAtBar[i] = PercentOfEquity21;
        inBuy21 = 1;
    }

    if( Buy22[i] AND totpos < maxtotpos )
    {
        if( totpos == 0 )
        {
            Buy[i] = 1;
        }
        else
            if( totpos > 0 )
            {
                Buy[i] = sigScaleIn;
            }

        totpos = totpos + PercentOfEquity22;
        actionAtBar[i] = PercentOfEquity22;
        inBuy22 = 1;
    }

    if( Buy23[i] AND totpos < maxtotpos )
    {
        if( totpos == 0 )
        {
            Buy[i] = 1;
        }
        else
            if( totpos > 0 )
            {
                Buy[i] = sigScaleIn;
            }

        totpos = totpos + PercentOfEquity23;
        actionAtBar[i] = PercentOfEquity23;
        inBuy23 = 1;
    }

    if( Sell21[i] AND inBuy21 )
    {
        totpos = totpos - PercentOfEquity21;
        actionAtBar[i] = PercentOfEquity21;

        if( totpos == 0 )
        {
            Sell[i] = 1;
        }
        else
            if( totpos > 0 )
            {
                Buy[i] = sigScaleOut;
            }

        inBuy21 = 0;
    }

    if( Sell22[i] AND inBuy22 )
    {
        totpos = totpos - PercentOfEquity22;
        actionAtBar[i] = PercentOfEquity22;

        if( totpos == 0 )
        {
            Sell[i] = 1;
        }
        else
            if( totpos > 0 )
            {
                Buy[i] = sigScaleOut;
            }

        inBuy22 = 0;
    }

    if( Sell23[i] AND inBuy23 )
    {
        totpos = totpos - PercentOfEquity23;
        actionAtBar[i] = PercentOfEquity23;

        if( totpos == 0 )
        {
            Sell[i] = 1;
        }
        else
            if( totpos > 0 )
            {
                Buy[i] = sigScaleOut;
            }

        inBuy23 = 0;
    }

    totalPositions[i] = totpos;
}

SetChartBkColor( ColorRGB( 0, 0, 0 ) );
SetChartOptions( 0, chartShowArrows | chartShowDates );
Plot( C, "C", colorWhite, styleCandle, Null, Null, 0, 0, 1 );
Plot( MA( C, 10 ), "Ma10", colorYellow, styleLine | styleNoRescale, Null, Null, 0, 0, 1 );
Plot( MA( C, 20 ), "Ma20", colorViolet, styleLine | styleNoRescale, Null, Null, 0, 0, 1 );
Plot( MA( C, 50 ), "Ma50", colorPaleTurquoise, styleLine | styleNoRescale, Null, Null, 0, 0, 1 );
Plot( MA( C, 200 ), "Ma200", colorBlue, styleLine | styleNoRescale, Null, Null, 0, 0, 1 );
Plot( totalPositions, "total positions", colorGold, styleLine | styleOwnScale | styleStaircase, 0, 150, 0, 0, 1 );

Title =
    "actionAtBar: " + actionAtBar +
    EncodeColor( colorGold ) + "\n totalPositions (PercentOfEquity): " + totalPositions + EncodeColor( colorWhite ) +
    "\n Ref( totalPositions, -1 ): " + Ref( totalPositions, -1 ) +
    "\n Buy: " + Buy +
    "\n Sell: " + Sell +
    "\n Buy21: " + Buy21 +
    "\n Buy22: " + Buy22 +
    "\n Buy23: " + Buy23 +
    "\n Sell21: " + Sell21 +
    "\n Sell22: " + Sell22 +
    "\n Sell23: " + Sell23;

PlotShapes( IIf( Buy == 1, shapeUpArrow, shapeNone ), colorDarkGreen, 0, L, -20 );
PlotShapes( IIf( Buy == 1, shapeSmallCircle, shapeNone ), colorWhite, 0, BuyPrice, 0 );
PlotShapes( IIf( Buy == sigScaleIn, shapeUpArrow, shapeNone ), colorBrightGreen, 0, L, -20 );
PlotShapes( IIf( Buy == sigScaleIn, shapeSmallCircle, shapeNone ), colorWhite, 0, BuyPrice, 0 );
PlotShapes( IIf( Buy == sigScaleOut, shapeDownArrow, shapeNone ), colorGold, 0, H, -20 );
PlotShapes( IIf( Buy == sigScaleOut, shapeSmallCircle, shapeNone ), colorWhite, 0, BuyPrice, 0 );
PlotShapes( IIf( Sell, shapeDownArrow, shapeNone ), colorRed, 0, H, -20 );
PlotShapes( IIf( Sell, shapeSmallCircle, shapeNone ), colorWhite, 0, SellPrice, 0 );

PlotShapes( IIf( Buy21, shapeUpTriangle, shapeNone ), colorBrightGreen, 0, L, -40 );
PlotShapes( IIf( Sell21, shapeDownTriangle, shapeNone ), colorBrightGreen, 0, H, -40 );
PlotShapes( IIf( Buy22, shapeUpTriangle, shapeNone ), colorYellow, 0, L, -40 );
PlotShapes( IIf( Sell22, shapeDownTriangle, shapeNone ), colorYellow, 0, H, -40 );
PlotShapes( IIf( Buy23, shapeUpTriangle, shapeNone ), colorAqua, 0, L, -40 );
PlotShapes( IIf( Sell23, shapeDownTriangle, shapeNone ), colorAqua, 0, H, -40 );

SetPositionSize( abs( actionAtBar ), IIf( Buy OR Sell, spsPercentOfEquity, spsNoChange ) );
2 Likes