*! qadf - Quantile ADF Unit Root Test
*! Version 1.0.0, February 2026
*! Author: Dr. Merwan Roudane
*! Email: merwanroudane920@gmail.com
*!
*! Reference:
*!   Koenker, R., Xiao, Z., 2004.
*!   Unit Root Quantile Autoregression Inference.
*!   Journal of the American Statistical Association 99, 775-787.
*!   DOI: 10.1198/016214504000001114
*!
*! Critical Values:
*!   Hansen, B. (1995). Rethinking the Univariate Approach to Unit Root Tests.
*!   Econometric Theory, 11, 1148-1171.

program define qadf, rclass sortpreserve
    version 14.0

    syntax varname(ts) [if] [in], [           ///
        TAU(real 0.5)                         /// Quantile (0 < tau < 1)
        Model(string)                         /// Model: c (constant) or ct (constant+trend)
        MAXLags(integer 8)                    /// Maximum ADF lags
        IC(string)                            /// Info criterion: aic, bic, tstat
        Level(cilevel)                        /// Confidence level
        NOPRint                               /// Suppress output
        ]

    *--------------------------------------------------------------------------
    * Load Mata library
    *--------------------------------------------------------------------------
    capture findfile _qadf_mata.ado
    if _rc {
        di as error "Required file _qadf_mata.ado not found."
        di as error "Ensure the QADF package is properly installed."
        exit 601
    }
    qui run `"`r(fn)'"'

    *--------------------------------------------------------------------------
    * Input validation
    *--------------------------------------------------------------------------
    marksample touse
    _ts timevar panelvar if `touse', sort onepanel
    markout `touse' `timevar'

    * Validate tau
    if `tau' <= 0 | `tau' >= 1 {
        di as error "tau() must be strictly between 0 and 1"
        exit 198
    }

    * Validate model
    if "`model'" == "" {
        local model "c"
    }
    else {
        local model = lower("`model'")
        if !inlist("`model'", "c", "ct") {
            di as error "model() must be {bf:c} (constant) or {bf:ct} (constant + trend)"
            exit 198
        }
    }

    * Validate IC
    if "`ic'" == "" {
        local ic "aic"
    }
    else {
        local ic = lower("`ic'")
        if !inlist("`ic'", "aic", "bic", "tstat") {
            di as error "ic() must be {bf:aic}, {bf:bic}, or {bf:tstat}"
            exit 198
        }
    }

    * Validate maxlags
    if `maxlags' < 0 {
        di as error "maxlags() must be non-negative"
        exit 198
    }

    * Check sample size
    qui count if `touse'
    local N = r(N)
    if `N' < 20 {
        di as error "insufficient observations (need at least 20, have `N')"
        exit 2001
    }

    *--------------------------------------------------------------------------
    * Compute QADF test via Mata
    *--------------------------------------------------------------------------
    tempvar y_temp
    qui gen double `y_temp' = `varlist' if `touse'

    mata: qadf_compute("`y_temp'", `tau', "`model'", `maxlags', "`ic'", "`touse'")

    * Retrieve results from Mata
    local qadf_stat = r(qadf_stat)
    local coef_stat = r(coef_stat)
    local rho_tau   = r(rho_tau)
    local rho_ols   = r(rho_ols)
    local alpha_tau = r(alpha_tau)
    local delta2    = r(delta2)
    local half_life = r(half_life)
    local opt_lags  = r(lags)
    local nobs      = r(nobs)
    local cv1       = r(cv1)
    local cv5       = r(cv5)
    local cv10      = r(cv10)

    *--------------------------------------------------------------------------
    * Significance determination
    *--------------------------------------------------------------------------
    local stars ""
    local decision "Cannot reject H0: Evidence consistent with unit root"
    if `qadf_stat' < `cv1' {
        local stars "***"
        local decision "Reject H0 at 1%: Strong evidence of stationarity"
    }
    else if `qadf_stat' < `cv5' {
        local stars "**"
        local decision "Reject H0 at 5%: Evidence of stationarity"
    }
    else if `qadf_stat' < `cv10' {
        local stars "*"
        local decision "Reject H0 at 10%: Weak evidence of stationarity"
    }

    * Half-life display
    if `half_life' == . {
        local hl_display "{c -}{c -}{c -}"
    }
    else {
        local hl_display : di %9.2f `half_life'
    }

    * Model label
    if "`model'" == "c" {
        local model_label "Constant"
    }
    else {
        local model_label "Constant + Trend"
    }

    *--------------------------------------------------------------------------
    * Display beautiful results table
    *--------------------------------------------------------------------------
    if "`noprint'" == "" {

        di
        di as txt "{hline 78}"
        di as txt "{col 5}{bf:Quantile ADF Unit Root Test}"
        di as txt "{col 5}{it:Koenker, R., Xiao, Z. (2004). JASA, 99, 775-787.}"
        di as txt "{hline 78}"
        di
        di as txt "{col 5}Variable:{col 25}" as res "`varlist'" ///
           as txt "{col 45}Number of obs{col 62}=" as res %10.0f `nobs'
        di as txt "{col 5}Model:{col 25}" as res "`model_label'" ///
           as txt "{col 45}Optimal lags{col 62}=" as res %10.0f `opt_lags'
        di as txt "{col 5}Quantile (tau):{col 25}" as res %7.3f `tau' ///
           as txt "{col 45}IC:{col 62}" as res %10s "`ic'"
        di
        di as txt "{hline 78}"
        di as txt "{col 25}{bf:Coefficient Estimates}"
        di as txt "{hline 78}"
        di
        di as txt "{col 5}rho_1(tau) [QR]:{col 35}" as res %12.6f `rho_tau'
        di as txt "{col 5}rho_1     [OLS]:{col 35}" as res %12.6f `rho_ols'
        di as txt "{col 5}alpha_0(tau):{col 35}" as res %12.6f `alpha_tau'
        di as txt "{col 5}delta-sq:{col 35}" as res %12.6f `delta2'
        di as txt "{col 5}Half-life:{col 35}" as res "`hl_display'"
        di
        di as txt "{hline 78}"
        di as txt "{col 25}{bf:Test Statistics}"
        di as txt "{hline 78}"
        di
        di as txt "{col 5}{bf:t_n(tau):{col 35}}" as res %12.4f `qadf_stat' ///
           as txt "  `stars'"
        di as txt "{col 5}U_n(tau) = n(rho-1):{col 35}" as res %12.4f `coef_stat'
        di
        di as txt "{hline 78}"
        di as txt "{col 25}{bf:Critical Values (Hansen, 1995)}"
        di as txt "{hline 78}"
        di
        di as txt "{col 5}" _col(20) "1%" _col(35) "5%" _col(50) "10%"
        di as txt "{col 5}" _col(17) as res %10.4f `cv1' ///
           _col(32) as res %10.4f `cv5' ///
           _col(47) as res %10.4f `cv10'
        di
        di as txt "{hline 78}"
        di as txt "{col 5}{bf:Decision:}"
        if "`stars'" != "" {
            di as res "{col 5}`decision'"
        }
        else {
            di as txt "{col 5}`decision'"
        }
        di as txt "{hline 78}"
        di as txt "{col 5}Note: *** p<0.01, ** p<0.05, * p<0.10"
        di as txt "{col 5}H0: Unit root (rho_1 = 1)  vs  H1: Stationarity (rho_1 < 1)"
        di as txt "{hline 78}"
    }

    *--------------------------------------------------------------------------
    * Return results
    *--------------------------------------------------------------------------
    return scalar N        = `nobs'
    return scalar tau      = `tau'
    return scalar lags     = `opt_lags'

    return scalar qadf     = `qadf_stat'
    return scalar Unstat   = `coef_stat'

    return scalar rho_tau  = `rho_tau'
    return scalar rho_ols  = `rho_ols'
    return scalar alpha_tau = `alpha_tau'
    return scalar delta2   = `delta2'
    return scalar half_life = `half_life'

    return scalar cv1      = `cv1'
    return scalar cv5      = `cv5'
    return scalar cv10     = `cv10'

    return local varname   "`varlist'"
    return local model     "`model'"
    return local ic        "`ic'"
    return local cmd       "qadf"
end