TB3流通市值过滤问题,无法获得流通市值并做上下限过滤
//------------------------------------------------------------------------
// 简称: StockPick_IndustryLeader
// 名称: 选股-行业龙头
// 类别: 策略应用
// 类型: 内建应用
// 修改: 增加流通市值绝对值过滤(小于100亿、大于500亿,可分别启用)
//------------------------------------------------------------------------

/* 行业龙头,30天成交额前10%,流通市值前10%,主营收入前30%,盈利,取120日涨跌幅前5% */ 
Params
    enum<String> IndustrytypeID(["F101022","F101021","F101026","F101003"]);   //F101022:申万2级分类 F101021:申万1级分类F101026:ZJH分类 F101003:TB分类
    String IndustryLeader ("行业龙头");    //推送到行情报价的三级板块名
    Numeric MarkNumber(2);                //标记的号码
    Array<Numeric> TurnoverPCT([30,10]); //n天成交金额排名前m,n=TurnoverPCT[0],m=TurnoverPCT[1]
    Numeric MarketCapPCT(10);            //流通市值前10%
    Numeric RevenuePCT(30);              //营业收入前30%
    Array<Numeric> zdfPCT([120,5]);      //满足前面所有条件的按n日涨跌幅排序取前面m,n=zdfPCT[0],m=zdfPCT[1]
    Numeric CrossDate(20260515);         //选股的截面日期
    Numeric writelog(0);                 //1写log,否则不写log
    
    // ==== 新增参数:流通市值绝对值过滤 ====
    Bool   EnableMinMarketCap(True);    // 是否启用最小市值过滤(True:启用, False:禁用)
    Numeric MinMarketCap(100);           // 最小流通市值(亿元),小于此值将被过滤
    Bool   EnableMaxMarketCap(True);    // 是否启用最大市值过滤(True:启用, False:禁用)
    Numeric MaxMarketCap(500);           // 最大流通市值(亿元),大于此值将被过滤
   
    
Vars  
    //基础数据定义
    Dic<Array<Numeric>> tbCapital("TB_CAPITAL_CIRCULATIONSHARES"); //数据中心》基础数据》股本结构》流通股份
    Dic<Array<Numeric>> tbRevenue("TB_INCOME_REVENUE");            //数据中心》基础数据》利润分配表》营业收入
    Dic<Array<Numeric>> tbprofit("TB_INCOME_PROFIT");              //数据中心》基础数据》利润分配表》利润汇总
    
    //循环订阅所有板块,不需要重置
    Global Numeric IdyNum(0);            //当前板块在板块数组IdyNamearr的序号
    Global Array<String> IdyNamearr;    //板块数组    
    Global Integer i(0);
    
    //需要重置区域
    //推送选股和标记专用
    Global String tmpSyms;          //自定义合约的股票    
    Global String tmpIds; 
    Global String tmpDesps;
    
    //其它变量
    Global Array<Numeric> mv;      //流通市值(亿元)
    Global Array<Numeric> zdf120;  //涨跌幅
    Global Array<Numeric> turnover30; //成交金额
    Global Array<Numeric> revenue; //营业收入
    Global Array<Numeric> profit; //净利润
    Global Array<Numeric> flag;  //选股标识
    Global Array<Integer> BarStatus2Flag(0); //数据源到最后一根的标识
    Global Integer BarStatus2FlagCount(0);//数据源满足最后一根的个数
    
    
Defs
    //写日志,方便代码调试
    Integer msgbox(StringRef msg)
    {
        if(writelog==1)
            FileAppend(".\\log\\"+FormulaName, "[" + DateTimeToString(SystemDateTime) + "] " + msg);
        Return 0;
    }
    
    //从基础数据读取行业板块名称,依据板块名称从基础数据读取板块内品种名称,订阅品种bar数据
    Bool SubscribeData()
    {
        //清空数组,准备新的板块选股
        ArrayClear(mv);
        ArrayClear(zdf120);
        ArrayClear(turnover30);
        ArrayClear(revenue);
        ArrayClear(profit);
        ArrayClear(flag);
        ArrayClear(BarStatus2Flag);//清空标识
        BarStatus2FlagCount=0;
        //获取当前是第几个板块
        if(IdyNum==0) 
        {
            if(IndustrytypeID=="F101003")
                IdyNum=1;//F101003第0个值的板块为全部,所以从1开始是行业板块
            GetDicValue("TB_INDUSTRY",IndustrytypeID,CrossDate,IdyNamearr);
        }        
        //写日志
        msgbox("idnum="+Text(IdyNum)+"/"+Text(GetArraySize(IdyNamearr)-1));
        //获取A股所有板块
        //订阅数据,追加的数据源
        Array<String> subSymbols; 
        //板块节点(科创板) 如果为空则不再添加数据
        String IdyName=IdyNamearr[IdyNum];        
        PushStatusMsg("正在执行["+IdyName+"],"+Text(IdyNum)+"/"+Text(GetArraySize(IdyNamearr)-1));
        if(IdyName<>"") 
        {
            GetDicValue("TB_INDUSTRY",IdyName,SystemDateTime(),subSymbols);
        }
        msgbox(TextArray(subSymbols));
        for i=0 to GetArraySize(subSymbols)-1
        {
            msgbox("起始日期"+text(DateAdd(CrossDate,-180)));
            SubscribeBar(subSymbols[i],"1d",DateAdd(CrossDate,-180),CrossDate);
                //msgbox("订阅"+subSymbols[i]+"成功");
            //Else
                //msgbox("订阅"+subSymbols[i]+"失败");
        }
        Range[0:DataCount-1]
        {
            AddDataFlag(Enum_Data_RolloverBackWard());//设置后复权
        } 
        Return True;
    }
    
    //1、检查订阅数据的完整性,对于空数据的品种进行退订。2、设置后复权
    Bool CheckData()
    {
        Integer datanum;
        Array<Integer> BarCountarr;
        //统计下各数据源的bar数
        Range[i=0:DataCount-1]
        {
            BarCountarr[i]=BarCount;
        }   
        msgbox(TextArray(BarCountarr));
        msgbox("检查前数据源数量="+text(DataCount));
        //倒序剔除无数据的数据源
        datanum=DataCount;
        for i=0 to DataCount-1
        {
            if(BarCountarr[datanum-1-i]==0 or BarCountarr[datanum-1-i]==InvalidInteger)
            {
                //msgbox("删除数据,因为bar数目="+Text(BarCountarr[datanum-1-i]));
                UnsubscribeBar(datanum-1-i);
            }
        }
        msgbox("检查后数据源数量="+text(DataCount));
        if(DataCount==0)
        {
            IdyNum=IdyNum+1; //选过的板块数量加1
            if(IdyNum<GetArraySize(IdyNamearr))
            {
                ReStart(false);   //重启订阅下一个板块
            }Else
            {
                PushStatusMsg("选股完成");
                AddStrategyFlag(Enum_Strategy_Finished);//正常停止策略运行
            }
        }    
        Return True;
    }
    
    //计算指标
  //计算指标
Bool countIndicators()
{
    Range[i=0:DataCount-1]  
    {
        // 无条件执行序列函数(每根Bar都会调用,避免警告)
        Numeric tempTurnover30 = Summation(TurnOver, TurnoverPCT[0]);
        
        if(((BarCount==1 && barstatus==0) ||barstatus==2) && BarStatus2Flag[i]==0)
        {
            if(close==InvalidNumeric) 
            {
                mv[i]=-1;
                zdf120[i]=-1;
                turnover30[i]=-1;
            } 
            Else
            {
                zdf120[i]=close/close[zdfPCT[0]];  
                mv[i]=close/Rollover*tbCapital[0][1]*0.0001*0.0001;
                turnover30[i] = tempTurnover30;   // 只在最后一根Bar记录
            }
            revenue[i]=tbRevenue[0][1];
            profit[i]=tbprofit[0][11];
            BarStatus2Flag[i]=1;
            BarStatus2FlagCount=BarStatus2FlagCount+1;
            msgbox(TextArray(BarStatus2Flag));    
        } 
    }
    Return True;    
}
    
    //指标排序
    Bool SortIndicators()
    {
        //站在data0上对所有品种进行排序,最后结果存为一个数组
        msgbox("开始排序!");
        msgbox(TextArray(BarStatus2Flag));
        msgbox(TextArray(zdf120));  //确认数值都获取到
        msgbox(TextArray(mv));
        msgbox(TextArray(turnover30));
        msgbox(TextArray(revenue));
        msgbox(TextArray(profit));
        
        // 1. 流通市值排名前MarketCapPCT%
        Array<Integer> id1;
        Array<Integer> id2;
        for i=0 to DataCount-1   //下标数组的初始化赋值
        {
            id1[i]=i; 
            id2[i]=i;
        }
        SortIds(mv,id1,id2,0,DataCount-1,False);//对流通市值进行倒序排序
        Array<Numeric> flagmv;
        for i=0 to DataCount-1
        {
            if(id2[i]<DataCount*MarketCapPCT*0.01)   //选择排名考前的标识为1
                flagmv[i]=1;
            Else
                flagmv[i]=0;
        }
        
        // 2. 新增:流通市值绝对值过滤(小于MinMarketCap或大于MaxMarketCap)
        Array<Numeric> flagMarketCapAbs;
        for i=0 to DataCount-1
        {
            flagMarketCapAbs[i] = 1; // 默认通过
            if(EnableMinMarketCap and mv[i] < MinMarketCap)
                flagMarketCapAbs[i] = 0;
            if(EnableMaxMarketCap and mv[i] > MaxMarketCap)
                flagMarketCapAbs[i] = 0;
        }
        // 日志输出市值过滤情况
        if(EnableMinMarketCap or EnableMaxMarketCap)
        {
            Integer passCount = 0;
            for i=0 to DataCount-1
                if(flagMarketCapAbs[i]==1) passCount = passCount + 1;
            msgbox("市值绝对值过滤:启用最小"+IIFString(EnableMinMarketCap,Text(MinMarketCap)+"亿","否")+
                   ",启用最大"+IIFString(EnableMaxMarketCap,Text(MaxMarketCap)+"亿","否")+
                   ",通过数量="+Text(passCount)+"/"+Text(DataCount));
        }
        
        // 3. 30天成交额排名前TurnoverPCT[1]%
        ArrayClear(id1);
        ArrayClear(id2);
        for i=0 to DataCount-1
        {
            id1[i]=i;
            id2[i]=i;
        }
        SortIds(turnover30,id1,id2,0,DataCount-1,False);
        Array<Numeric> flagturnover30;
        for i=0 to DataCount-1
        {
            if(id2[i]<DataCount*TurnoverPCT[1]*0.01)
                flagturnover30[i]=1;
            Else
                flagturnover30[i]=0;
        }
        
        // 4. 营业收入排名前RevenuePCT%
        ArrayClear(id1);
        ArrayClear(id2);
        for i=0 to DataCount-1
        {
            id1[i]=i;
            id2[i]=i;
        }
        SortIds(revenue,id1,id2,0,DataCount-1,False);
        Array<Numeric> flagrevenue;
        for i=0 to DataCount-1
        {
            if(id2[i]<DataCount*RevenuePCT*0.01)
                flagrevenue[i]=1;
            Else
                flagrevenue[i]=0;
        }
        
        // 5. 盈利过滤(净利润>0)
        Array<Numeric> flagprofit;
        for i=0 to DataCount-1
        {
            if(profit[i]>0)
                flagprofit[i]=1;
            Else
                flagprofit[i]=0;
        }
        
        // 日志输出各条件计数
        msgbox(TextArray(flagmv));
        msgbox(TextArray(flagturnover30));
        msgbox(TextArray(flagrevenue));
        msgbox(TextArray(flagprofit));
        
        // 6. 汇总所有条件(原4项 + 新增市值绝对值过滤)
        Array<Numeric> flag1;
        for i=0 to DataCount-1
        {
            flag1[i]=flagmv[i]*flagturnover30[i]*flagrevenue[i]*flagprofit[i]*flagMarketCapAbs[i];
        }
        
        // 7. 按涨跌幅排序,取前zdfPCT[1]%
        ArrayClear(id1);
        ArrayClear(id2);
        for i=0 to DataCount-1
        {
            id1[i]=i;
            id2[i]=i;
        }
        SortIds(zdf120,id1,id2,0,DataCount-1,False);
        Numeric k=0;
        Numeric targetCount = RoundUp(zdfPCT[1]*0.01*DataCount,0);
        for i=0 to DataCount-1   //循环选取股票,当达到数量上限则停止选股
        {
            if(flag1[id1[i]]==1 and k<targetCount)
            {    
                flag[id1[i]]=1;
                k=k+1;
            }
            Else
                flag[id1[i]]=0;
        }
        msgbox("最终入选股票数量="+Text(k));
        Return True;
    }
        
    //选股并推送到板块
    Bool PickStock_Send()
    {
        if(GetArraySize(flag)>0)
        {
            msgbox(TextArray(flag));
        }
        Range[i=0:DataCount-1]
        {                        
            if(flag[i]==1)
            {
                tmpSyms = tmpSyms+Symbol+","; 
                tmpIds=tmpIds+Text(MarkNumber)+","; //写标记
                tmpDesps=tmpDesps+Text(SystemDateTime,9)+",";   
            }               
        } 
        Map<String,String> context;    //写标记用            
        Map<String,String> mySyms;   //推送自定义合约的MAP
        mySyms["合约集合"]=tmpSyms;//选股合约
        mySyms["板块名称"]="策略选择_"+IndustryLeader ;//自定义行情设置,格式是:一级板块_二级板块
        If(IdyNum==1)
            mySyms["添加方式"]="override";//更新方式:override,append
        Else
            mySyms["添加方式"]="append";
        context["合约集合"]=tmpSyms;//选股合约  
        context["标记编号集合"]=tmpIds;//合约标记ID【1-10】  
        context["标记内容集合"]=tmpDesps;//标记内容    
        if(tmpSyms<>"") 
        {
            PublishEvent("系统-选股事件",mySyms,"行情报价");//发送选股事件到行情报价
            PublishEvent("系统-标记事件",context,"行情报价"); //写标记
        }
        tmpSyms="";
        tmpIds="";
        tmpDesps="";
        IdyNum=IdyNum+1; //选过的板块数量加1
        if(IdyNum<GetArraySize(IdyNamearr))
        {
            ReStart(false);   //重启订阅下一个板块
        }Else
        {
            PushStatusMsg("选股完成");
            AddStrategyFlag(Enum_Strategy_Finished);//正常停止策略运行
        }
        Return True;               
    }
    
Events
    OnInit()
    {
        //订阅数据
        SubscribeData();
    }
    OnReady()
    {
        //检查数据
        CheckData();
    }
    OnBar(ArrayRef<Integer> indexs)    
    {        
        //计算指标
        countIndicators();
        //指标排序
        
        //所有数据源都结束再选股
        if(BarStatus2FlagCount==DataCount)
        {
            SortIndicators();
            //选股并推送到板块
            PickStock_Send();
        }
    }

//------------------------------------------------------------------------
// 编译版本    GS2010.12.08
// 版权所有    TradeBlazer Software 2003-2045
// 更改声明    TradeBlazer Software保留对TradeBlazer平
//            台每一版本的TradeBlazer公式修改和重写的权利
//------------------------------------------------------------------------

TB3流通市值过滤问题,无法获得流通市值并做上下限过滤,比如过滤掉流通市值小于100亿,大于500亿的股票。麻烦老师指点一下,谢谢!

有没有计算多头市值、空头市值和总持仓市值的函数
固定市值开仓问题
最大持仓市值不给看
最大开仓市值问题
股票除权除息市值
老师好,净市值计算的问题
信号过滤
过滤信号
过滤器回测
过滤集合竞价

有没有函数可以直接查询流值和PE?


是不能用了吗?有没有其他替代的过滤方法?