*! version 1.0.7 15dec2022 JM. Domenech, R. Sesma
/*
scct: Stochastic curtailment (immediate command)
*/
program define scct
version 12
syntax anything(id="argument numlist"), /*
*/ Alpha(numlist max=1 >0 <50) Beta(numlist max=1 >0 <50) [CP1(numlist max=1 >=50 <100) nst(string)]
local n : word count `anything'
if (`n'!=3) print_error "t, cp0 and cp1 are needed"
tokenize `anything'
local t `1' //Percentage of information accrued
local cp0 `2' //Conditional power under null hypothesis
local cp1 `3' //Conditional power under alternative hypothesis
confirm number `t'
confirm number `cp0'
confirm number `cp1'
if (`t'<=0 | `t'>100) print_error "invalid t -- 0 < t <= 100"
if (`cp0'<50 | `cp0'>=100) print_error "invalid cp0 -- 50 <= cp0 < 100"
if (`cp1'<50 | `cp1'>=100) print_error "invalid cp1 -- 50 <= cp1 < 100"
*Compute results
local t = `t'/100
local z0= invnormal(1-`cp0'/100)
local z1= invnormal(`cp1'/100)
foreach i of numlist 1/2 {
local za`i' = invnormal(1-`alpha'/(`i'*100))
local zb`i' = `za`i'' + invnormal(1-`beta'/100)
local ztr`i' = (`za`i'' - `z0'*sqrt(1-`t'))/sqrt(`t')
if (`i'==2) local ztr2n = -1*`ztr2'
local ptr`i' = (1-normal(`ztr`i''))*`i'
local zta`i' = (`za`i'' - `z1'*sqrt(1-`t') - `zb`i''*(1-`t'))/sqrt(`t')
if (`i'==2) local zta2n = -1*`zta2'
local pta`i' = (1-normal(`zta`i''))*`i'
}
*Print results
di as res "STOCHASTIC CURTAILMENT: Clinical trials"
if ("`nst'"!="") di as txt "{bf:STUDY:} `nst'"
di
di as txt "Risk: Alpha= {bf:`alpha'}% Beta= {bf:`beta'}%"
di as txt "Conditional power: under H0= {bf:`cp0'}% under H1= {bf:`cp1'}%"
local t = `t'*100
di as txt "Accrued information= {bf:`t'}%"
di
di as txt "{hline 6}{c TT}{hline 23}{c TT}{hline 22}{c TT}{hline 25}"
di as txt " TEST {c |}" _col(16) "Z value" _col(31) "{c |}" _col(41) "P value" _col(54) "{c |} DECISION"
di as txt "{hline 6}{c +}{hline 23}{c +}{hline 22}{c +}{hline 25}"
di as txt " TWO {c |}{bf:+infinity} to" _col(21) as res %9.5f `ztr2' " {c |} 0" /*
*/ as txt _col(41) " to " as res %7.6f `ptr2' as txt " {c |} STOP: Beneficial effect"
if (`zta2'>0) {
di as txt "SIDED {c |}" as res %9.5f `ztr2' as txt " to " as res %9.5f `zta2' " {c |} " /*
*/ %7.6f `ptr2' as txt " to " as res %7.6f `pta2' as txt " {c |} CONTINUE"
di as res _col(7) "{c |}" as res %9.5f `zta2' as txt " to " as res %9.5f `zta2n' " {c |} " /*
*/ %7.6f `pta2' as txt " to " as res "1" as txt _col(54) "{c |} STOP: Lack of power (H0)"
di as res _col(7) "{c |}" as res %9.5f `zta2n' as txt " to " as res %9.5f `ztr2n' " {c |} " /*
*/ %7.6f `pta2' as txt " to " as res %7.6f `ptr2' as txt " {c |} CONTINUE"
}
else {
di as txt "SIDED {c |}" as res %9.5f `ztr2' as txt " to " as res %9.5f `ztr2n' " {c |} " /*
*/ %7.6f `ptr2' as txt " to " as res "1" as txt _col(54) "{c |} CONTINUE"
}
di as res _col(7) "{c |}" as res %9.5f `ztr2n' as txt " to {bf:-infinity}" _col(31) "{c |} " /*
*/ as res %7.6f `ptr2' as txt " to " as res "0" _col(54) as txt "{c |} STOP: Harmful effect"
di as txt "{hline 6}{c +}{hline 23}{c +}{hline 22}{c +}{hline 25}"
di as txt " ONE {c |}{bf:+infinity} to" _col(21) as res %9.5f `ztr1' " {c |} 0" /*
*/ as txt _col(41) " to " as res %7.6f `ptr1' as txt " {c |} STOP: Beneficial effect"
di as txt "SIDED {c |}" as res %9.5f `ztr1' as txt " to " as res %9.5f `zta1' " {c |} " /*
*/ %7.6f `ptr1' as txt " to " as res %7.6f `pta1' as txt _col(54) "{c |} CONTINUE"
di as res _col(7) "{c |}" as res %9.5f `zta1' as txt " to {bf:-infinity}" _col(31) "{c |} " /*
*/ as res %7.6f `pta1' as txt " to " as res "1" _col(54) as txt "{c |} STOP: Lack of power (H0)"
di as txt "{hline 6}{c BT}{hline 23}{c BT}{hline 22}{c BT}{hline 25}"
end
program define print_error
args message
display in red "`message'"
exit 198
end