TASC Issue Indicators & Ideas in afl

Technical Analysis of Stocks & Commodities (TASC) is a highly respected monthly publication catering to traders, investors, and developers interested in technical analysis, trading systems, and market indicators. Since its inception in 1982, TASC has been a go-to resource for cutting-edge trading ideas, algorithmic strategies, and in-depth explorations of technical indicators.
This thread is initiative from myself to focus on:

Introducing and summarizing notable new indicators from each TASC issue
Implementing these indicators in Amibroker using AFL
Sharing insights, improvements, and adaptations where relevant

:date: Latest TASC Issue Highlights

As of May 2025, the latest TASC issue includes indicators and strategies such as:

  • A new variation on adaptive moving averages
  • A momentum-based trend strength filter
  • Techniques on market regime classification

I aim to convert these ideas into ** AFL code** with visual plots, parameter tuning options, and compatibility with Amibroker’s backtesting features.

If anyone is interested or want a specific indicator from previous issue I can give it a try as well.
I understand there might be some redundancy in the TASC indicator or idea is much similar to already available indicator, but at the end the slightest improvement that you can add to your trading system can give you extreme edge in the market.

4 Likes

Here is my trial for Trading the channel May 2025 Issue
I directly converted python to afl with some artificial intelligence support, replaced raw implementation with available functions in afl

// -------- INPUT PARAMETERS -------------
period = Param("Period", 140, 10, 500, 1);     // Linear regression lookback
zone   = Param("Zone", 0.20, 0.01, 1.0, 0.01); // Zone width for targets
// ---------------------------------------
/*
// Calculate Linear Regression Line
x = Cum(1); // Simulated x-values (1,2,3,...)
x0 = Ref(x, -period + 1); // Align to rolling window

sumX  = Sum(x0, period);
sumY  = Sum(Close, period);
sumXY = Sum(x0 * Close, period);
sumXX = Sum(x0 * x0, period);

m = (period * sumXY - sumX * sumY) / (period * sumXX - sumX * sumX);
b = (sumY - m * sumX) / period;
*/
m=LinRegSlope(Close,period);
lrLine =LinearReg(Close,period); //m * x0 + b;

// Distance between price and regression line
diff = Close - lrLine;

// Compute upper and lower channel lines
maxDiff = hhv(diff, period);
minDiff = llv(diff, period);
upperLine = lrLine + maxDiff;
lowerLine = lrLine + minDiff;

// Compute upper and lower targets
range = upperLine - lowerLine;
upperTarget = upperLine - zone * range;
lowerTarget = lowerLine + zone * range;

// --------- Plotting ----------
Plot(Close, "Close", colorDefault, styleLine);
Plot(lrLine, "LR Line", colorBlue, styleLine);
Plot(upperLine, "Upper Line", colorGreen, styleDashed);
Plot(lowerLine, "Lower Line", colorRed, styleDashed);
Plot(upperTarget, "Upper Target", colorGreen, styleDots);
Plot(lowerTarget, "Lower Target", colorRed, styleDots);

// Optional slope display in Title
slopeDisp = StrFormat("Slope = %.5f", (m));
Title = Name() + " - Linear Regression Channel\n" + slopeDisp;

[Trading The Channel May 2025 Python code ] (TRADERS’ TIPS - MAY 2025)

7 Likes

Ultimate OScillator TASC June 2025 Python

#
# import required python libraries
#
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import math
#
# Retrieve S&P 500 daily price data from Yahoo Finance
# 




#
# Python code for highpass, rms and ultimate oscillator functions highlighted in the article
# 

def calc_highpass(price, period):
    
    a1 = math.exp(-1.414 * math.pi / period)
    df=pd.DataFrame()
    df['close']=price
    df['return_array']=df['close']
    b1 = 2 * a1 * math.cos(math.radians(1.414 * 180 / period))
    c2 = b1
    c3 = -a1 * a1
    c1 = (1 + c2 - c3)/4

    out_values = []
    for i in range(len(price)):
        if i >= 4:
            out_values.append(
                c1*(price[i] - 2*price[i-1] + price[i-2]) + c2*out_values[i-1] + c3*out_values[i-2]
            )
        else:
![UltimateOscillator|690x407](upload://AaUyyYpS5TK68EBtPZaZ9GkYNdL.png)
            out_values.append(price[i])
    df['return_array']=out_values
    return df['return_array'].to_numpy()


def calc_rms(price):

    length = len(price)
    sum_sq = 0
    for count in range(length):
        sum_sq += price.iloc[count] * price.iloc[count]
    return np.sqrt(sum_sq / length)


def moving_average(a, n=3):
    ret = np.cumsum(a, dtype=float)
    ret[n:] = ret[n:] - ret[:-n]
    return ret[n - 1:] / n    

def calc_ultimate_oscillator(close, band_edge, band_width):

	
	df=pd.DataFrame()
	df['close']=close
	df['return_array']=close
	df['hp1']= calc_highpass(df['close'], band_width * band_edge)
	df['hp2'] = calc_highpass(df['close'], band_edge)

	df['signal'] = df['hp1']-df['hp2']
	os.system("say 'Hello, this is Python speaking.'") 	
	df['rms'] = df['signal'].rolling(100).apply(calc_rms)
	df['return_array'] = df['signal']/df['rms']
	
	return df['return_array'].to_numpy()

#
# S&P500 applying EMA and Ultimate Oscillator
# 
def main() :
	band_edge=30
	band_width=2
	length = band_edge
	#df = ohlcv.copy()
	#ema1 = calc_ema(close, period=length)
	#a=calc_ultimate_oscillator(close, band_edge, band_width)

if __name__ == "__main__":
    main()

1 Like

What's the point of using Python when Ultimate indicator is built-in function in AFL????

Also, instead of python, take Tradestation code, it is way better to translate than Python to AFL.
And ChatGPT/Gemini would translate that for you easily.

2 Likes

@Tomasz it is just proof of concept, so that any other article in python can be directly implemented using the same way if python code is available, and I wanted to see the challenges using amipy.

As I said, it is way better to translate Tradestation code into AFL than anything else.

2 Likes

You got me interested to read why ! @Tomasz
I was just converting it before now I understood that it uses easy language and there are certain patterns that easily converted to afl

But again I was challenging myself a bit for this one, since I needed to include some machine learning later on with python and I was pretty much trying to be active in this topic :grin:
But anyway I might give up on TASC indicators for now and focus on some ML

Python simply doesn't have functions typical for technical analysis platform, therefore Python code must implement things the way that is not needed in specialized TA platform like Tradestation or AmiBroker. Tradestation Easy Language, even though it is very different from AFL, has specialized functions that can be transferred to other TA platform relatively easily.

2 Likes
/* --------------------------------------------------------------
 Custom Directional Oscillator
Author by Vitali Apirine
TASC June 2023 

The stochastic distance oscillator can be used with securities
or indexes that trend. It is also suitable for trading
ranges. The SDO can be used to identify buying/selling
opportunities in harmony with the larger trend.
The SDO can also be used to identify trend changes.
A break in support or a bearish price crossover
--------------------------------------------------------------
 This indicator measures the normalized magnitude of price
 change and applies a direction (positive for up, negative
 for down), then smooths the result with an EMA.
--------------------------------------------------------------
*/

// SECTION 1: USER-DEFINABLE PARAMETERS
// Use Param() to create easy-to-adjust inputs in the chart window.

LBPeriod = Param( "Stochastic Lookback", 200, 10, 500, 1 );
Period   = Param( "Price Change Period", 12, 1, 100, 1 );
Pds      = Param( "Smoothing Period", 3, 1, 100, 1 );

// SECTION 2: CORE CALCULATIONS

// 1. Calculate the absolute price change over 'Period' bars.
Dist = Abs( C - Ref( C, -Period ) );

// 2. Normalize the price change into a 0-1 range (like a Stochastic Oscillator).
// We use IIf() to prevent division-by-zero errors in flat markets.
HHV_Dist = HHV( Dist, LBPeriod );
LLV_Dist = LLV( Dist, LBPeriod );
Denominator = HHV_Dist - LLV_Dist;

D = SafeDivide(( Dist - LLV_Dist ) , Denominator);

// 3. Assign a direction to the normalized value.
// If price is up, value is positive. If price is down, value is negative.
DD = IIf( C > Ref( C, -Period ), D, IIf( C < Ref( C, -Period ), -D, 0 ) );

// 4. Calculate the final indicator line by smoothing DD with an EMA and scaling by 100.
// The original `Mov(..., E)` is equivalent to AFL's `EMA()`.
FinalOscillator = EMA( DD, Pds ) * 100;

// SECTION 3: PLOTTING

_SECTION_BEGIN( "stochastic distance oscillator (SDO)" );

// Plot the final smoothed oscillator.
Plot( FinalOscillator, "Oscillator", colorBlue, styleLine | styleThick );

// Plot a zero line for reference.
Plot( 0, " ", colorGrey50, styleDashed );
Plot( 40, "", colorGrey50, styleDashed );
Plot( -40, "", colorGrey50, styleDashed );

_SECTION_END();

Buy =Cross(finaloscillator,-40);
Sell=Cross(40,finaloscillator);
Plotshapes (sell*shapeDownarrow,colorred,0,finaloscillator);
Plotshapes (buy*shapeUparrow,colorGreen,0,finaloscillator);

//https://www.traders.com/Documentation/FEEDbk_docs/2023/06/TradersTips.html**stron//g text**
// Optional: Add a title with current values to the chart pane.
Title = EncodeColor( colorwhite ) + Name() + " (" +
        NumToStr( LBPeriod, 1.0 ) + ", " +
        NumToStr( Period, 1.0 ) + ", " +
        NumToStr( Pds, 1.0 ) + ") | Value: " +
        EncodeColor( colorBlue ) + NumToStr( FinalOscillator, 2.2 );



2 Likes

Does anyone have the implementation of point and line chart for amibroker relate to aricle
TRADERS’ TIPS - NOVEMBER 2025 ?

If you mean the .afl, it's in the actual article, just not in the Traders' Tips section.

2 Likes

Thanks @Chris25

I added quick conversion from Easy language
amibroker.com/members/library/formula.php?id=1612

1 Like