In this article, we provide a detailed walkthrough of the Matlab code used to perform the trend-following backtest discussed in our paper, A Century of Profitable Industry Trends.
We recommend reading the paper first, which you can access here.
Using Kenneth French’s freely available database, we built an industry-based long-only trend-following portfolio. This portfolio is based on daily data from 48 industry portfolios, covering the period from 1926 to 2024. Our study compares the performance of this momentum-based strategy with a passive Buy & Hold approach over the past century.
Our findings demonstrate the superior performance of momentum-based portfolios. The strategy includes several parameters, none of which were optimized in-sample, meaning the performance statistics could be improved by fine-tuning these parameters.
At the end of this article, we provide another Matlab code that allows you to quickly explore how changing different parameters can impact the portfolio’s profitability.
To enhance the readability and make the code more intuitive for novice quant researchers, we intentionally avoided more complex coding procedures that may result in improved computational efficiency.
Step-by-Step Guide Through the Backtesting Process
Below, we give an overview of the main building blocks behind the backtesting procedure.
MATLAB: MATLAB is a high-level programming language and environment developed by MathWorks. It is widely used for numerical computing, data analysis, algorithm development, and visualization. You can try MATLAB for FREE for 20 hours by visiting the official MathWorks website. Alternatively, a MATLAB Home license costs $149 for personal use.
How to Read This Post
For each step, we will provide the full code first, then explain it step by step. If a step depends on a utility function (a function we wrote that is not built-in MATLAB), we will provide its code after the step code directly before the explanation.
Step 1: Download and Process Industry Data
Overview
This step involves downloading daily return data for 48 industry portfolios from Kenneth French‘s database, processing the data to prepare it for backtesting, and saving the necessary variables for later use. The process includes downloading, unzipping, reading CSV data, cleaning, and structuring the data.
Step 1 Code:
Click to see the MATLAB code for Step 1
MATLAB
% Download Data From Frenchurl = 'https://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/48_Industry_Portfolios_daily_CSV.zip';zipFile = websave('temp.zip', url);pause(1);unzip(zipFile, 'temp_folder');pause(1);csvFile = dir(fullfile('temp_folder', '*.csv'));csvFilePath = fullfile('temp_folder', csvFile.name);movefile(csvFilePath, 'output.csv', 'f');delete(zipFile); pause(1);rmdir('temp_folder', 's');clear p csvData = readtable('output.csv');p.industry_names = csvData.Properties.VariableNames(2:end);rows_nan = find(isnan(table2array(csvData(:,1))));% MktCap ind_weightingfrom = 1; until = rows_nan(1)-1;data = table2array(csvData(from:until,1:end)); p.ret = data(:,2:end)/100;p.caldt = datenum(num2str(data(:,1)),'yyyymmdd'); % change in case daily datap.ret(find(p.ret<=-0.99))=NaN;%%clearvars -except pp.mkt_ret = market_french_reconciled(p.caldt); % download the time-series of market return and match the position with respect to daysp.tbill_ret = tbill_french_reconciled(p.caldt); % download the time-series of tbill daily ret and match the position with respect to dayssave('industry48.mat','p')
Needed functions for Step 1:
market_french_reconciled
tbill_french_reconciled
Click to see the MATLAB code for market_french_reconciled
MATLAB
functiony = market_french_reconciled(caldt)url = 'https://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/F-F_Research_Data_Factors_daily_CSV.zip';zipFile = websave('temp.zip', url);pause(1);unzip(zipFile, 'temp_folder');pause(1);csvFile = dir(fullfile('temp_folder', '*.csv'));csvFilePath = fullfile('temp_folder', csvFile.name);pause(1);movefile(csvFilePath, 'output.csv', 'f');delete(zipFile); pause(2);rmdir('temp_folder', 's');csvData = readtable('output.csv', 'ReadVariableNames', false);rows_nan = find(isnan(table2array(csvData(:,1))));% MktCap Weightingfrom = rows_nan(1); until = rows_nan(2)-1;data = table2array(csvData(from:until,1:end)); data(find(isnan(data(:,1))),:)=[];ret_mkt = data(:,2)/100+data(:,5)/100; % add back the risk freecaldt_mkt = datenum(num2str(data(:,1)),'yyyymmdd'); % change in case daily dataT = length(caldt);y = NaN(T,1);X_dates = datetime(caldt, 'ConvertFrom', 'datenum');[isMember, idx] = ismember(caldt_mkt, caldt);% Create a mapping of caldt_mkt to ret_mkt using idxmappedReturns = NaN(size(caldt));mappedReturns(idx(isMember)) = ret_mkt(isMember);% Assign the returns to y based on matching indicesy = mappedReturns;end
Click to see the MATLAB code for tbill_french_reconciled
MATLAB
functiony = tbill_french_reconciled(caldt)url = 'https://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/F-F_Research_Data_Factors_daily_CSV.zip';zipFile = websave('temp.zip', url);pause(1);unzip(zipFile, 'temp_folder');pause(1);csvFile = dir(fullfile('temp_folder', '*.csv'));csvFilePath = fullfile('temp_folder', csvFile.name);pause(1);movefile(csvFilePath, 'output.csv', 'f');delete(zipFile); pause(2);rmdir('temp_folder', 's');csvData = readtable('output.csv', 'ReadVariableNames', false);rows_nan = find(isnan(table2array(csvData(:,1))));% MktCap Weightingfrom = rows_nan(1); until = rows_nan(2)-1;data = table2array(csvData(from:until,1:end)); data(find(isnan(data(:,1))),:)=[];ret_mkt = data(:,5)/100; % caldt_mkt = datenum(num2str(data(:,1)),'yyyymmdd'); % change in case daily dataT = length(caldt);y = NaN(T,1);X_dates = datetime(caldt, 'ConvertFrom', 'datenum');[isMember, idx] = ismember(caldt_mkt, caldt);% Create a mapping of caldt_mkt to ret_mkt using idxmappedReturns = NaN(size(caldt));mappedReturns(idx(isMember)) = ret_mkt(isMember);% Assign the returns to y based on matching indicesy = mappedReturns;end
1.1 Download and Store Data
This code downloads a ZIP file from the specified URL, which contains CSV files for 48 industry portfolios. The websave function is used to download and save the file as ‘temp.zip’. The pause commands are used to ensure that file operations complete before proceeding. The ZIP file is then extracted into a folder named ‘temp_folder’.
After extracting the files, the script searches for CSV files within the ‘temp_folder’ and moves the found CSV file to the current working directory, renaming it to ‘output.csv’. This ensures that subsequent operations are performed on the correct file.
Clears variable p to ensure it does not contain old data. The script then reads the processed CSV file into a table, extracts industry names, and identifies rows containing NaN values which could indicate missing data.
Converts the table to an array for easier manipulation, slicing the data until the first NaN occurrence. It normalizes the returns by dividing by 100 to convert percentage to a decimal format. Dates are converted to MATLAB’s numeric date format for consistency in subsequent operations. Extreme negative returns, usually associated with missing data, are marked as NaN to avoid distorting statistical calculations.
Click to see the MATLAB code
MATLAB
from = 1; until = rows_nan(1)-1;data = table2array(csvData(from:until,1:end)); p.ret = data(:,2:end)/100;p.caldt = datenum(num2str(data(:,1)),'yyyymmdd');p.ret(find(p.ret<=-0.99))=NaN;
1.6 Download and Align Additional Data
Calls custom functions to download and align market and T-bill returns with the dates from the industry data. These functions are crucial for ensuring that all data used in subsequent analysis is synchronized to the same time frame.
The final step saves the prepared dataset to a MATLAB file, ‘industry48.mat’. This file will be used in subsequent steps of the backtesting process.
Saving the database allows the quant researcher to import data quicker for future backtest.
Click to see the MATLAB code
MATLAB
save('industry48.mat','p')
Step 2: Load Database and Compute Indicators and Signals
Overview
In this step, after loading the pre-processed financial data (industry48.mat), various technical indicators and trading signals are computed. This includes setting up the parameters for these indicators, generating hypothetical price series from total returns, and calculating volatility, moving averages, Donchian channels, Keltner bands, and the corresponding long and short trading signals. These calculations are foundational for the strategy’s decision-making process in the subsequent backtesting phase.
Step 2 Code:
Click to see the MATLAB code
MATLAB
clear allload('industry48.mat')% INDICATORS PARAMETERSup_day = 20;down_day = 40;kelt_mult = 2;adr_vol_adj = 1.4; % we noticed that ATR is usually 1.4xVol(close2close)kelt_mult = kelt_mult*adr_vol_adj;% FROM DAILY TOTAL RETURNS, CREATE THE HYPOTHETICAL PRICE TIME-SERIES FOR% EACH INDUSTRYp.price = cumprod(1+p.ret,'omitmissing');% Rolling Volatility of Daily Returnsp.vol = Rolling_Vol(p.ret,up_day,'omtinan');% Technical Indicatorsp.ema_down = Rolling_Ema(p.price,down_day,'omitnan');p.ema_up = Rolling_Ema(p.price,up_day,'omitnan') ;% Donchain Channels (Eq.5 and Eq.6)p.donc_up = Rolling_Max(p.price,up_day);p.donc_down = Rolling_Min(p.price,down_day);% Keltner Bands (Eq. 3 and 4)p.kelt_up = p.ema_up + kelt_mult*Rolling_Mean(abs(price2change(p.price,1)),up_day,'omitnan');p.kelt_down = p.ema_down - kelt_mult*Rolling_Mean(abs(price2change(p.price,1)),down_day,'omitnan');% Model Bands p.long_band = min(p.donc_up,p.kelt_up); % Eq.7p.short_band = max(p.donc_down,p.kelt_down); % Eq.11% Model Long Signalp.long_signal = p.price>=lag_TS(p.long_band,1) & lag_TS(p.long_band,1)>lag_TS(p.short_band,1);
functionema = rolling_ema(price, window, nanflag)% Size of the price matrixT = size(price, 1);N = size(price, 2);% Initialize output matrixema = NaN(T, N);% Smoothing factoralpha = 2 / (window + 1);% Loop through each element and compute EMAfor n = 1:Nfor t = 2:Tif isnan(price(t, n))if strcmp(nanflag, 'omitnan')% If omitnan flag is used, skip NaN valuescontinue;endelse% If the previous EMA is NaN (start of the series), initialize it as the first data pointif isnan(ema(t-1, n)) ema(t-1, n) = price(t-1, n);end% Compute the EMA ema(t, n) = alpha * price(t, n) + (1 - alpha) * ema(t-1, n);endendendend
functiony=Rolling_Mean(price,window,nanflag)T = size(price,1);N = size(price,2);y = NaN(T,N);for i=window:1:T y(i,:)=mean(price(i-window+1:i,:),1,nanflag);endy(find(isnan(price)==1))=NaN; % if input variable is missing, consider NaNend
Click to see the MATLAB code for price2change
MATLAB
functiony=price2change(price,n)% This function converts prices into returns T=size(price,1); N=size(price,2); y=NaN(T,N); y(n+1:end,:)=price(n+1:T,:)-price(1:T-n,:); y(isnan(y))=NaN; end
Click to see the MATLAB code for lag_TS
MATLAB
functiony=lag_TS(data,n)% This function lag the data matrix to n-times T=size(data,1); N=size(data,2); y=NaN(T,N);if n>0 y(n+1:T,:) = data(1:T-n,:);elseif n<0 n = -n; y(1:T-n,:) = data(1+n:T,:); else y = data;end y(isnan(y))=NaN; end
2.1 Load Data
This section begins by clearing the MATLAB workspace with clear all to ensure no residual data from previous sessions affects the current process. It then loads the dataset ‘industry48.mat’ which was prepared in Step 1.
Click to see the MATLAB code
MATLAB
clear allload('industry48.mat')
2.2 Set Indicator Parameters
Parameters for the technical indicators are defined here. up_day and down_day specify the periods for calculating moving averages and other metrics. The Keltner Channel multiplier (kelt_mult) is multiplied by an adjustment factor (adr_vol_adj) since the database we are using does not include high and low prices (more information can be found on page 7 of our paper)
Click to see the MATLAB code
MATLAB
up_day = 20;down_day = 40;kelt_mult = 2;adr_vol_adj = 1.4; % we noticed that ATR is usually 1.4xVol(close2close)kelt_mult = kelt_mult*adr_vol_adj;
2.3 Compute Price Series
Constructs a hypothetical price time-series from daily total returns for each industry by sequentially multiplying the compounded returns. This is essential for the subsequent calculation of technical indicators which require price data.
Click to see the MATLAB code
MATLAB
p.price = cumprod(1+p.ret,'omitmissing');
2.4 Calculate Volatility
Calculates rolling volatility over a specified number of days (up_day). This metric is crucial for risk management and sizing positions based on current market conditions.
Click to see the MATLAB code
MATLAB
p.vol = Rolling_Vol(p.ret, up_day, 'omitnan');
2.5 Generate Technical Indicators
This section computes various technical indicators:
Exponential Moving Averages (EMA) for up and down days.
Donchian Channels which are the maximum and minimum of the price over a specified period.
Keltner Channels which use the EMA and the mean absolute price change to set channel boundaries.
Trading signals are derived by comparing the current price against the previously computed trading bands:
Long Signal: Generated when the current closing price is above the long band as of yesterday’s close. To prevent contradicting signals, we also require that yesterday’s long band should be above yesterday’s short band.
Step 3 involves executing the backtest using the previously calculated indicators and signals to simulate trading on a historical data set. It focuses on dynamic portfolio management based on the computed technical indicators and trading signals, with adjustments made for exposure, position sizing, and stop-loss levels. The process includes setting up initial parameters such as investment capital and risk measures, dynamically updating exposures and weights based on trading signals, and calculating returns to measure performance.
Step 3 Code
Click to see the MATLAB code
MATLAB
AUM_0 = 1;invest_cash = "YES"; % invest cash in short-term bonds, and pay for cash borrowedtarget_vol = 0.02; % the risk budget per industry is target_vol/Nmax_leverage = 2; % max leverage at portfolio level.max_not_trade = 0.20; % Limit the max equity exposure per industry% initiliaze portfolio variablesp.exposure = zeros(size(p.price)); % matrix that take 1 or 0 based on if we hold a long positionp.ind_weight = zeros(size(p.price)); % optimal weight at industry levelp.trail_stop_long = NaN(size(p.price)); % trailing stop lossN_ind = length(p.industry_names); % how many industries in database% for each industry, compute the optimal weight at daily frequency, and% update the level of trailing stop in case the stop has not been hitT = length(p.caldt);for j = 1:length(p.industry_names)for t = 1:Tif ~isnan(p.ret(t,j)) && ~isnan(p.long_band(t,j)) % start the backtest when key-variable are not NaN% EXPOSURE CALCULATION% Open a new long position if yesterday exposure was 0 and% today we have a long_signal at the closureif p.exposure(t-1,j) <= 0 && p.long_signal(t,j) == 1% New long signal p.exposure(t,j) = 1; p.trail_stop_long(t,j) = p.short_band(t,j); % set the value for the trailing stop% leverage required to reach the target vol lev_vol = target_vol/p.vol(t,j);% optimal weight at industry level p.ind_weight(t,j) = p.exposure(t,j)*lev_vol;% Yesterday we were long. Today the price didn't cross the trailing stop. We confirm the long epxosure and we update the trailing stop elseif p.exposure(t-1,j) == 1 && p.price(t,j) > max(p.trail_stop_long(t-1,j),p.short_band(t,j)) p.exposure(t,j) = 1; % the long exposure is confirmed p.trail_stop_long(t,j) = max(p.trail_stop_long(t-1,j),p.short_band(t,j)); % update trailing stop as in Eq.12% leverage required to reach the target vol lev_vol = target_vol/p.vol(t,j);% optimal weight at industry level%p.ind_weight(t,j) = min(p.ind_weight(t-1,j),lev_vol); % in the paper i used this but it's a small typo, it deflated%the results in terms of IRR p.ind_weight(t,j) = p.exposure(t,j)*lev_vol;% yesterday we were long but today the closing price is below the trailing stop elseif p.exposure(t-1,j) == 1 && p.price(t,j) <= max(p.trail_stop_long(t-1,j),p.short_band(t,j)) % set exposure and weight to 0 p.exposure(t,j) = 0; p.ind_weight(t,j) = 0;endendendend% Initialize a strucutre str where we store the results at aggregate% portfolio levelstr.caldt = p.caldt;str.available = sum(~isnan(p.ret),2,'omitmissing'); % how many industries were available each day (some industries may became available later in the database)str.port_weight = p.ind_weight./str.available; % optimal weight at portfolio level. See Eq.8% Limit the exposure of each industry at "max_not_trade"idx_above_max_not = find(str.port_weight > max_not_trade);str.port_weight(idx_above_max_not) = max_not_trade;% In case the portfolio exposure exceed the maximum leverage, rescaled each% position proportionallystr.sum_exposure = sum(str.port_weight,2,'omitmissing'); % implied daily leverageidx_above_max_lev = find(str.sum_exposure > max_leverage); % find days when the maximum leverage was exceededstr.port_weight(idx_above_max_lev,:) = str.port_weight(idx_above_max_lev,:)./str.sum_exposure(idx_above_max_lev)*max_leverage; % Eq10str.sum_exposure = sum(str.port_weight,2,'omitmissing');% Compute portfolio daily returnsstr.ret_long = sum(lag_TS(str.port_weight,1).*p.ret,2,'omitmissing');str.ret_tbill = (1-sum(lag_TS(str.port_weight,1),2,'omitmissing')).*p.tbill_ret; % return of cash investment/borrowedif strcmp(invest_cash,"YES") % include cash returns only when selected str.ret_long = str.ret_long + str.ret_tbill;end% Compute the timeseries of the AUMstr.AUM = AUM_0*cumprod(1 + str.ret_long, 'omitnan');str.AUM_SPX = AUM_0*cumprod(1 + p.mkt_ret, 'omitnan'); % Calculating the adjusted AUM for SPX
3.1 Initialize Portfolio Variables and Parameters
The script sets initial conditions including assets under management (AUM), whether cash is invested in short-term bonds, target volatility, maximum leverage, and limits on industry exposure. Arrays for tracking exposure, weights, and trailing stops are initialized based on the number of industries and data points.
The nested loops traverse each industry and trading day. The script checks for valid data and calculates exposure based on the presence of a long signal and the status of trailing stops. When conditions are met, exposure and industry weights are adjusted to reflect the desired risk level and strategy rules.
The script adjusts portfolio weights to ensure compliance with risk management rules such as maximum notional trade size per industry and overall leverage limits. Weights are scaled down if the aggregate exposure exceeds predefined thresholds.
Calculates daily returns for the portfolio, including returns from cash investments if specified. The returns are then used to compute the growth of assets under management (AUM), both for the strategy and relative to a market index, providing a measure of performance over time.
functiontable_statistics = table_of_stats(AUM,N_assets,names,caldt,mkt_ret,tbill_ret) table_statistics = struct();for s = 1:size(AUM,2) ret = price2return(AUM(:,s),1); table_statistics(s).strategy = names{s}; table_statistics(s).assets = N_assets(s); table_statistics(s).irr = round((prod(1+ret,'omitmissing')^(252/length(ret))-1)*100,1); table_statistics(s).vol = round(std(ret,'omitmissing')*sqrt(252)*100,1); table_statistics(s).sr = round(mean(ret,'omitmissing')/std(ret,'omitmissing')*sqrt(252),2); table_statistics(s).sortino = round(SortinoRatio(ret)*sqrt(252),2); table_statistics(s).ir_d = computeHitRatio(ret,caldt,"daily"); table_statistics(s).ir_m = computeHitRatio(ret,caldt,"monthly"); table_statistics(s).ir_y = computeHitRatio(ret,caldt,"yearly"); table_statistics(s).skew_d = round(skewness(ret),2); table_statistics(s).skew_m = round(computeSkewness(ret,caldt,"monthly"),2); table_statistics(s).skew_y = round(computeSkewness(ret,caldt,"yearly"),2); table_statistics(s).mdd = round(maxdrawdown(AUM(:,s))*100,0); XX = [mkt_ret-tbill_ret]; YY = ret-tbill_ret; regr = fitlm(XX,YY); coef = regr.Coefficients.Estimate; tstas = regr.Coefficients.tStat; table_statistics(s).alpha = round(coef(1)*100*252,2); table_statistics(s).alpha_t = tstas(1); table_statistics(s).beta = round(coef(2),2); table_statistics(s).beta_t = tstas(2); table_statistics(s).worst_ret= round(min(ret)*100,2); table_statistics(s).worst_day= datestr(caldt(find(ret == min(ret)))); table_statistics(s).best_ret = round(max(ret)*100,2); table_statistics(s).best_day = datestr(caldt(find(ret == max(ret))));end originalTable = struct2table(table_statistics);% Step 1: Extract the column names colNames = originalTable.Properties.VariableNames;% Step 2: Transpose the data transposedData = table2array(originalTable)';% Step 3: Create the new table newTable = array2table(transposedData);%, 'VariableNames', colNames);% Step 4: Add the original column names as a new column newTable = addvars(newTable, colNames', 'Before', 1);% Step 5: Name the column of the new Table newTable.Properties.VariableNames = [" " names];% Display the result table_statistics = newTable;end
Click to see the MATLAB code of SortinoRatio
MATLAB
functionsortinoRatio = SortinoRatio(returns)% Compute the mean return meanReturn = mean(returns,'omitmissing');% Compute the downside deviation downsideReturns = returns(returns < 0); downsideDeviation = std(downsideReturns,'omitmissing');% Compute the Sortino Ratio sortinoRatio = (meanReturn) / downsideDeviation;end
Click to see the MATLAB code of computeHitRatio
MATLAB
functionhitRatio = computeHitRatio(ret,caldt, timeframe)% Ensure the timeframe is valid validTimeframes = {'daily', 'monthly', 'yearly'};if ~ismember(timeframe, validTimeframes) error('Invalid timeframe. Choose "daily", "monthly", or "yearly".');end% Convert datenum to datetime for easier manipulation dates = datetime(caldt, 'ConvertFrom', 'datenum'); returns = ret;% Calculate the Hit Ratio based on the timeframeswitch timeframecase'daily' hitRatio = round(sum(returns > 0) / sum(abs(returns) > 0) * 100, 0);case'monthly'% Group by year and month [yearMonth, ~, idx] = unique(dates.Year*100 + dates.Month); monthlyReturns = accumarray(idx, returns, [], @(x) prod(1 + x,'omitmissing') - 1); hitRatio = round(sum(monthlyReturns > 0) / sum(abs(monthlyReturns) > 0) * 100, 0);case'yearly'% Group by year [years, ~, idx] = unique(dates.Year); yearlyReturns = accumarray(idx, returns, [], @(x) prod(1 + x,'omitmissing') - 1); hitRatio = round(sum(yearlyReturns > 0) / sum(abs(yearlyReturns) > 0) * 100, 0);otherwise error('Unexpected timeframe.');endend
Click to see the MATLAB code of computeSkewness
MATLAB
functionskw = computeSkewness(ret,caldt, timeframe)% Ensure the timeframe is valid validTimeframes = {'daily', 'monthly', 'yearly'};if ~ismember(timeframe, validTimeframes) error('Invalid timeframe. Choose "daily", "monthly", or "yearly".');end% Convert datenum to datetime for easier manipulation dates = datetime(caldt, 'ConvertFrom', 'datenum'); returns = ret;% Calculate the Hit Ratio based on the timeframeswitch timeframecase'daily' skw = skewness(returns);case'monthly'% Group by year and month [yearMonth, ~, idx] = unique(dates.Year*100 + dates.Month); monthlyReturns = accumarray(idx, returns, [], @(x) prod(1 + x,'omitmissing') - 1); skw = skewness(monthlyReturns);case'yearly'% Group by year [years, ~, idx] = unique(dates.Year); yearlyReturns = accumarray(idx, returns, [], @(x) prod(1 + x,'omitmissing') - 1); skw = skewness(yearlyReturns);;otherwise error('Unexpected timeframe.');endend
4.1 Compute Portfolio Returns
This script visualizes the performance of the investment strategy relative to a market index. It plots the cumulative asset value of the strategy and the market index on a logarithmic scale to better illustrate growth trends over time. The graph is customized with specific formatting options to enhance readability and presentation.
Generates a summary statistics table that includes important metrics such as internal rates of return, volatility, Sharpe ratio, and other performance indicators. This table is calculated using a custom function table_of_stats, which processes the asset management data and returns to provide a comprehensive statistical breakdown of the strategy’s performance over time.
You can download the full code from here and run it directly cell by cell in your MATLAB! Remember to run cell 0 (at the bottom) to load needed functions!
If you are interested in a version where you only want to change parameters, this is a version where the backtest is put in a function and you just edit the parameters to see the results faster.