精华内容
下载资源
问答
  • PDM 和 ERP 数据对接面临的问题点 PDM 和 ERP 是在企业信息化过程中发挥重要作用的系统随着它们的发展 两者出现了功能上的交叉当同时维护相同部分数据时就可能出现数据不一致的 情况而且信息无法在两个系统之间相互...
  • 浅谈数据对接

    千次阅读 2020-03-16 15:47:19
    浅谈数据对接 一般来讲,数据对接就是将己方收集到的客户数据转化为平台方的规范要求的数据格式上传的一种方式。各个平台对于数据的要求格式各不相同。那怎么才能快速做好数据对接,而且重复劳动尽量少地完成,返工...

    浅谈数据对接

    	一般来讲,数据对接就是将己方收集到的客户数据转化为平台方的规范要求的数据格式上传的一种方式。各个平台对于数据的要求格式各不相同。那怎么才能快速做好数据对接,而且重复劳动尽量少地完成,返工也要尽量少。我觉得要分几个步骤去进行。切记不能一头热栽在文档上,死命地对,很可能你的接口后期要崩死,考虑平台方的修改和己方数据的缺失或者并不完全符合的情况。
    1.粗略看下对接文档和客户需求(这个必须看,不看后期等着改死吧)。特别对日期敏感,数据对接很可能为了验收  ,有一段日期里的数据特别重要。
    2.了解收集到的客户数据,并将字段和了解到的对接文档字段一一对应。对于编码一定要重视,一般数据上传失败会在这里栽跟头。
    3.等了解了己方数据库字段和文档的对应关系后,别急着下手。还有一步是一定要做的。查看数据库的垃圾数据,想必大家都知道,但凡数据大了之后,总有垃圾数据会在上传的时候影响上传的数据的准确性。当然会有人建立日志去记录,上传数据的成功率。但是去搜索日志需要耗费精力,还要去确定问题的根源,会浪费大量时间。与其去后期处理,不如预先做好预防,提前将垃圾数据给筛掉,保证数据上传的精确。
    4.前面工作做完才能安心码代码编写接口将数据上传。
    

    下面举个例子 (后台框架mybatis+mvc)
    对接方式 :导出txt (昨天的数据) 再上传平台
    后台sql

        <select id="getMeatTzInHz" resultType="net.***.**.platform.meat.entity.MeatTzInHz">
    		SELECT
    			instock.slaughterCode,
    			instock.instockDate,
    			SUM(instock.checkInstockNum),
    			AVG(instock.price) 				AS price,
    			SUM(instock.quantityAndWeight)  AS quantityAndWeight,
    			SUM(instock.transportDeathNum)  AS transportDeathNum,
    			produceCode
    		FROM (
                     SELECT
                        COALESCE(trace_mainbody_employee.mainbody_record_info :: JSON ->> 'meatCommerceCode', '')  AS slaughterCode,
                        --主体编码
                        COALESCE(trace_mainbody_employee.mainbody_name, '')                                    AS slaughterName,
                        --主体名称
                        TO_CHAR(trace_instock.instock_date,'yyyyMMdd')                  		    AS instockDate,
                        --进场日期
                        COALESCE(substr(trace_mainbody_provider.mainbody_record_info :: JSON ->> 'commerceCode',1,9), '') AS ownerCode,
                        --货主编码
                        COALESCE(trace_mainbody_provider.mainbody_name, '')                               		 AS ownerName,
                        --货主名称
                        COALESCE(trace_batch.inspection_info :: JSON ->> 'CitypfTzPigCertCode', '')       		 AS checkCertCode,
                        --生猪产地检疫证号,--json格式要得到CitypfTzPigCertCode
                        CAST(COALESCE(trace_batch.batch_other_info :: JSON ->> 'detectionQuantity', '0') AS int) AS checkInstockNum,
                        --检疫证进场数量,--json格式要得到CitypfTzQuarantineCount
                        COALESCE(trace_batch.batch_price, 0)                                              		 AS price,
                        --批次单价
                        COALESCE(trace_batch.batch_quantity, 0)                                           		 AS quantityAndWeight
    
                        FROM
                            t_trace_instock trace_instock --入库基础
                            INNER JOIN t_trace_instock_detail trace_instock_detail
                        ON (
                            trace_instock.ID = trace_instock_detail.instock_id
                            AND trace_instock_detail.del_flg = '0'
                            )
                            INNER JOIN t_trace_mainbody trace_mainbody_employee --企业表
                            ON (
                            trace_mainbody_employee.trace_mainbody_code = trace_instock.trace_mainbody_code
                            AND trace_mainbody_employee.mainbody_type in ('101')
                            AND trace_mainbody_employee.del_flg = '0'
                            AND trace_mainbody_employee.mainbody_record_info :: JSON ->> 'meatCommerceCode' != ''
    						<if test="division != null and division != ''">
    							  AND split_part(trace_mainbody_employee.mainbody_record_info :: JSON ->> 'divisionName',',',2) like ('%' || #{division,jdbcType = VARCHAR} || '%')
    						</if>
    						<if test="mainBodyCode != null and mainBodyCode != ''">
    							AND main.mainbody_code = #{mainBodyCode,jdbcType = VARCHAR}
    						</if>
                            )
                            LEFT JOIN t_trace_mainbody trace_mainbody_provider --供应商表
                            ON (
                            trace_mainbody_provider.mainbody_code = trace_instock.supplier_code
                            AND trace_mainbody_provider.mainbody_type = '102'
                            AND trace_mainbody_provider.del_flg = '0'
                            )
                            INNER JOIN t_trace_batch trace_batch --批次表
                            ON (
                            trace_batch.batch_code = trace_instock_detail.batch_code
                            AND trace_batch.del_flg = '0'
                            )
                        WHERE
                            trace_mainbody_employee.mainbody_record_info :: JSON ->> 'nodeType' = '101'
                            AND trace_instock.del_flg = '0'
                          <![CDATA[
                            AND CAST(trace_instock.sys_reg_tmsp AS DATE) >= CAST(#{startTagSysRegTmsp,jdbcType = VARCHAR} AS DATE)
                            AND CAST(trace_instock.sys_reg_tmsp AS DATE) <= CAST(#{endTagSysRegTmsp,jdbcType = VARCHAR} AS DATE)
                          ]]>
    		) instock
    		GROUP BY instock.slaughterCode, instock.instockDate, produceCode
    	</select>
    
    

    实体

    public class MeatTzInHz implements Serializable {
    
        /**
         * 屠宰厂编码
         */
        protected String slaughterCode;
    
        /**
         * 进厂日期
         */
        protected String instockDate;
    
        /**
         * 检疫证进场数量
         */
        protected int checkInstockNum;
    
        /**
         * 采购价
         */
        protected double price;
    
        /**
         * 实际数量和重量
         */
        protected double quantityAndWeight;
    
        /**
         * 途亡数
         */
        protected int transportDeathNum;
    
        /**
         * 产地编码
         */
        protected String produceCode;
    
        @Override
        public String toString() {
            return  FileEnum.DIVIDE_COMMA.getSymbol() + slaughterCode +
                    FileEnum.DIVIDE_COMMA.getSymbol() + instockDate +
                    FileEnum.DIVIDE_COMMA.getSymbol() + checkInstockNum +
                    FileEnum.DIVIDE_COMMA.getSymbol() + price +
                    FileEnum.DIVIDE_COMMA.getSymbol() + quantityAndWeight +
                    FileEnum.DIVIDE_COMMA.getSymbol() + transportDeathNum +
                    FileEnum.DIVIDE_COMMA.getSymbol() + produceCode + FileEnum.ENTER_LINE_BREAK.getSymbol();
        }
    

    mapper

    List<MeatTzOutHz> getMeatTzOutHz(DataCondition dataCondition);
    

    service

        public List<MeatTzInHz> getMeatTzInHz(DataCondition dataCondition) {
            List<MeatTzInHz> meatTzInHzList = meatMapper.getMeatTzInHz(dataCondition);
            //验证数据非空
            if(CollectionUtils.isEmpty(meatTzInHzList)) {
                return new ArrayList<>();
            }
            return meatTzInHzList;
        }
    

    导出service(方法名自写,只剖了方法体) ExportService

            List<MeatTzOutHz> meatTzOutHzList = meatService.getMeatTzOutHz(dataCondition);
            meatTzOutHzList.stream()
                    .filter(meatTzOutHz -> StringUtils.isNotBlank(meatTzOutHz.getSlaughterCode()))
                    .forEach(meatTzOutHz -> {
                        String fileName = txtFileUtil.getFileName(FileEnum.POSTFIX_MEAT_TZ_OUT_HZ_TXT.getSymbol(), meatTzOutHz.getSlaughterCode(), meatTzOutHz.getOutstockDate());
                        try {
                            txtFileUtil.writeFileToDateDirectory(meatTzOutHz.toString(), fileName);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    });
    

    定时任务
    大同小异

        @Autowired
        private ExportService exportService;
    /**
    *  秒  分   时  日  月  年  
    */
        @Scheduled(cron = "0 30 4,11 * * ? ")
        private void grouppurchasing() {
            List<MainBody> mainBodyList = nodeService.getMainBodyByNodeType(2);
    
            if(CollectionUtils.isNotEmpty(mainBodyList)){
                logger.info("生成数据文件开始!");
                mainBodyList.forEach(mainBody -> {
                    logger.info("生成企业:{} 数据文件开始!", mainBody.getMainbodyName());
                    DataCondition dataCondition = new DataCondition();
                    dataCondition.setDivision("上海");
                    dataCondition.setStartTagSysRegTmsp(DateUtil.getYesterdayByDefultFormat());
                    dataCondition.setEndTagSysRegTmsp(DateUtil.getNowByDefultFormat());
                    //dataCondition.setNodeTypeList(Arrays.asList(PlatformConstant.NODE_TYPE_110));
                    dataCondition.setMainBodyCode(mainBody.getMainbodyCode());
    
                    baseNodeInfo(dataCondition ,true);
    
                    exportService.exportGpToTxt(dataCondition);
                    logger.info("生成企业:{} 数据文件结束!", mainBody.getMainbodyName());
                });
                logger.info("生成数据文件结束!");
            }
    
        }
    

    工具类 fileEnum txtFileUtil

    public enum FileEnum {
    POSTFIX_MEAT_TZ_OUT_TXT("{0}_{1}_T2.TXT"),;
        private String symbol;
    
        FileEnum(String symbol) {
            this.symbol = symbol;
        }
    
        public String getSymbol() {
            return symbol;
        }
    }
    
        public String getFileName(String pattern, Object... arguments) {
            if (arguments == null || arguments.length == 0) {
                return pattern;
            }
            return MessageFormat.format(pattern, arguments);
        }
        /**
         * 写文件
         *
         * @param line
         * @param fileName
         * @throws IOException
         */
        public void writeFileToDateDirectory(String line, String fileName) throws IOException {
            String dateDir = DateUtil.getYesterdayByDefultFormat() + "/";
            String dirFile = this.fileOutputDirectory + dateDir + fileName;
            byte[] buff = line.getBytes(Charset.forName("GBK"));
    
            FileOutputStream out = fileMap.get(dirFile);
            if (out == null) {
                File directoryFile = new File(this.fileOutputDirectory + dateDir);
                File file = new File(dirFile);
                if (!directoryFile.exists()) {
                    directoryFile.mkdirs();
                }
                // 文件不存在,创建
                if (!file.exists()) {
                    file.createNewFile();
                }
                // append 参数为false,覆盖原来的文件
                out = new FileOutputStream(file, false);
                fileMap.put(dirFile, out);
            }
            out.write(buff);
        }
    

    DateUtil

        private static Date add(Date date, int calendarField, int amount) {
            if (date == null) {
                throw new IllegalArgumentException("The date must not be null");
            } else {
                Calendar c = Calendar.getInstance();
                c.setTime(date);
                c.add(calendarField, amount);
                return c.getTime();
            }
        }
        /**
         * 增加天
         *
         * @param date
         * @param amount
         * @return
         */
        public static Date addDays(Date date, int amount) {
            return add(date, 5, amount);
        }
            /**
         * 获取昨天
         * @return
         */
        public static Date getYesterday() {
            return addDays(getNow(), -1);
        }
            /**
         * 把日期类型格式化成字符串
         *
         * @param date
         * @param format
         * @return
         */
        public static String convert2String(Date date, String format) {
            SimpleDateFormat formater = new SimpleDateFormat(format);
            try {
                return formater.format(date);
            } catch (Exception e) {
                return null;
            }
        }
            /**
         * 获取昨天的日期并转化为yyyyMMdd
         * @return
         */
        public static String getYesterdayByDefultFormat() {
            return convert2String(getYesterday(), DATE_FORMAT_YYYYMMDD);
        }
    

    到这里,应该能生成txt文件了。还有一步上传。
    平台方要求 生成zip 再用webservice的方式上传到平台
    先po功能代码 ,再给工具类

        /**
         * webservice  上传zip文件(一天一次)
         * 6:30 12:30
         */
        @Scheduled(cron = "0 30 6,12 * * ? ")
        private void uploadZipByWebservice() {
            //打包
            String zipPath = "/sh";
            String zipName = DateUtil.getYesterdayByDefultFormat();
            ZipUtils.createZipFile(zipPath,zipName);
            //地址
            String fileName = "sh" + zipName + ".zip";
            Identity identity  = new Identity();
            ReqEntity<Identity> reqEntity = new ReqEntity<>();
            identity.setFileName(fileName);
            identity.setFileCreateTime(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
            File file = new  File("/data/"+ fileName);
            identity.setFileSize(String.valueOf(file.length()));
            reqEntity.setIdentity(identity);
            reqUtil.sendXml(reqEntity);
        }
    

    看着很简洁 ,包含了三个工具类,和 两个实体类
    实体类

    @Data
    //只检测属性不检测方法了
    @JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY, getterVisibility=JsonAutoDetect.Visibility.NONE)
    public class Identity implements Serializable {
    
        private String UserName;
        private String Password;
        private String FileName;
        private String FileSize;
        private String FileCreateTime;
    }
    
    

    父类

    @Data
    //只检测属性不检测方法了
    @JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY, getterVisibility=JsonAutoDetect.Visibility.NONE)
    public class ReqEntity<Identity> implements Serializable {
    
        private String pfileType;
        private String pbuffer;
        private String usercode;
        private String userPass;
        private Identity identity;
        private  String pErrmasg;
    
    }
    

    其实就是定义一些字段,啥也没写。=。=
    工具类的话
    生成压缩文件 zipUtil

        /**
         * 创建压缩文件
         */
        public static void createZipFile(String saveFilePath ,String zipName) {
            FileOutputStream fileOutputStream = null;
            try {
                File zipFile = new File(saveFilePath + zipName.replaceAll("(.*?)(/*)$","$1") + ".zip");
                fileOutputStream = new FileOutputStream(zipFile);
                ZipUtils.toZip(saveFilePath + "/"+zipName+"/", fileOutputStream, false);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        /**
         * 压缩成ZIP 方法1
         *
         * @param srcDir           压缩文件夹路径
         * @param out              压缩文件输出流
         * @param KeepDirStructure 是否保留原来的目录结构,true:保留目录结构;
         *                         false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
         * @throws RuntimeException 压缩失败会抛出运行时异常
         */
        public static void toZip(String srcDir, OutputStream out, boolean KeepDirStructure)
                throws RuntimeException {
    
            long start = System.currentTimeMillis();
            ZipOutputStream zos = null;
            try {
                zos = new ZipOutputStream(out);
                File sourceFile = new File(srcDir);
                compress(sourceFile, zos, sourceFile.getName(), KeepDirStructure);
                long end = System.currentTimeMillis();
                logger.info("压缩完成,耗时:" + (end - start) + " ms");
            } catch (Exception e) {
                throw new RuntimeException("zip error from ZipUtils", e);
            } finally {
                if (zos != null) {
                    try {
                        zos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        /**
         * 递归压缩方法
         *
         * @param sourceFile       源文件
         * @param zos              zip输出流
         * @param name             压缩后的名称
         * @param KeepDirStructure 是否保留原来的目录结构,true:保留目录结构;
         *                         false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
         * @throws Exception
         */
        private static void compress(File sourceFile, ZipOutputStream zos, String name,
                                     boolean KeepDirStructure) throws Exception {
            byte[] buf = new byte[BUFFER_SIZE];
            if (sourceFile.isFile()) {
                // 向zip输出流中添加一个zip实体,构造器中name为zip实体的文件的名字
                zos.putNextEntry(new ZipEntry(name));
                // copy文件到zip输出流中
                int len;
                FileInputStream in = new FileInputStream(sourceFile);
                while ((len = in.read(buf)) != -1) {
                    zos.write(buf, 0, len);
                }
                // Complete the entry
                zos.closeEntry();
                in.close();
            } else {
                File[] listFiles = sourceFile.listFiles();
                if (listFiles == null || listFiles.length == 0) {
                    // 需要保留原来的文件结构时,需要对空文件夹进行处理
                    if (KeepDirStructure) {
                        // 空文件夹的处理
                        zos.putNextEntry(new ZipEntry(name + "/"));
                        // 没有文件,不需要文件的copy
                        zos.closeEntry();
                    }
                } else {
                    for (File file : listFiles) {
                        // 判断是否需要保留原来的文件结构
                        if (KeepDirStructure) {
                            // 注意:file.getName()前面需要带上父文件夹的名字加一斜杠,
                            // 不然最后压缩包中就不能保留原来的文件结构,即:所有文件都跑到压缩包根目录下了
                            compress(file, zos, name + "/" + file.getName(), KeepDirStructure);
                        } else {
                            compress(file, zos, file.getName(), KeepDirStructure);
                        }
                    }
                }
            }
        }
        /**
         * 根据文件路径读取文件转出 byte[]
         *
         * @param filePath 文件路径
         * @return 字节数组
         * @throws IOException
         */
        public static byte[] getFileToByteArray(String filePath) throws IOException {
            File file = new File(filePath);
            long fileSize = file.length();
            if (fileSize > Integer.MAX_VALUE) {
                return null;
            }
            FileInputStream fileInputStream = new FileInputStream(file);
            byte[] buffer = new byte[(int) fileSize];
            int offset = 0;
            int numRead = 0;
            while (offset < buffer.length && (numRead = fileInputStream.read(buffer, offset, buffer.length - offset)) >= 0) {
                offset += numRead;
            }
            // 确保所有数据均被读取
            if (offset != buffer.length) {
                logger.error("Could not completely read file : {}" , file.getName());
                throw new IOException("Could not completely read file " + file.getName());
            }
            fileInputStream.close();
            return buffer;
        }
        
    

    还有上传的一个工具类 reqUtil

        @Value("${webservice.url}")
        private String webUrl;
        /**
         * xml  上报方式
         * @param reqEntity
         * @return
         */
        public String sendXml( ReqEntity<Identity> reqEntity) {
            URL url = null;
            String fileName = reqEntity.getIdentity().getFileName();
            String fileSize = reqEntity.getIdentity().getFileSize();
            String createTime = reqEntity.getIdentity().getFileCreateTime();
            String fileStr = "";
            String responsMess  = "";
            try {
                url = new URL(webUrl);
                reqUtilLogger.info("requestUrl:" + url);
                HttpURLConnection con = (HttpURLConnection) url.openConnection();
                byte[] zipOutput = ZipUtils.getFileToByteArray("/data/"+ fileName);
                fileStr = new sun.misc.BASE64Encoder().encode(zipOutput);
    
                //拼接好xml
                StringBuffer sb = new StringBuffer();
                sb.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
                        "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" +
                        "  <soap:Header>\n" +
                        "    <Identify xmlns=\"FjUpdate1\">\n" +
                        "      <UserName>"+userName+"</UserName>\n" +
                        "      <Password>"+password+"</Password>\n" +
                        "      <FileName>"+fileName+"</FileName>\n" +
                        "      <FileSize>"+fileSize+"</FileSize>\n" +
                        "      <FileCreateTime>"+createTime+"</FileCreateTime>\n" +
                        "    </Identify>\n" +
                        "  </soap:Header>\n" +
                        "  <soap:Body>\n" +
                        "    <UpFile xmlns=\"FjUpdate1\">\n" +
                        "      <pFileType>" + fileName.split("\\.")[0] + "</pFileType>\n" +
                        "      <pBuffer>"+fileStr+"</pBuffer>\n" +
                        "      <usercode>"+userName+"</usercode>\n" +
                        "      <userpass>"+password+"</userpass>\n" +
                        "    </UpFile>\n" +
                        "  </soap:Body>\n" +
                        "</soap:Envelope>\n");
    
                String xmlStr = sb.toString();
                System.out.println(xmlStr);
                //设置好header信息
                con.setRequestMethod("POST");
                con.setRequestProperty("content-type", "text/xml; charset=utf-8");
                con.setRequestProperty("Content-Length", String.valueOf(xmlStr.getBytes().length));
    //      con.setRequestProperty("soapActionString", soapActionString);
    
                //post请求需要设置
                con.setDoOutput(true);
                con.setDoInput(true);
    
                //对请求body 往里写xml 设置请求参数
                OutputStream ops = con.getOutputStream();
                ops.write(xmlStr.getBytes());
                ops.flush();
                ops.close();
    
                //设置响应回来的信息
                InputStream ips = con.getInputStream();
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                byte[] buf = new byte[1024];
                int length = 0;
                while( (length = ips.read(buf)) != -1){
                    baos.write(buf, 0, length);
                    baos.flush();
                }
                byte[] responsData = baos.toByteArray();
                baos.close();
    
                //处理写响应信息
                responsMess = new String(responsData,"utf-8");
                reqUtilLogger.info("响应报文:"+ responsMess);
                reqUtilLogger.info(String.valueOf(con.getResponseCode()));
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return responsMess;
        }
    

    这里@value的参数就不po了,大家懂的自然懂,怎么配置。
    userName和password自行定义即可。

    这样,就大功告成了。(^-^)V。
    很多人会问,用这么多类,你的 maven需要导入很多依赖包
    基础的mybatis,springframework等的我就不po了,大家都知道的。然后就是正常的io依赖也没啥特别的。自行解决就好。

    展开全文
  • 数据对接没有实时在数据管理云平台实时填报.ppt
  • HQMS数据对接文档

    2013-04-25 18:55:31
    HQMS数据对接,卫生部数据接口,用于医院连接卫生部接口
  • hqchartPy2数据对接教程3-FINANCE数据FINANCE接口函数参数说明symolidperiodrightkcountjobID返回数据格式单数值类型时间序列数据tushare数据对接例子对接数据代码交流QQ群hqchartPy动态库地址HQChart代码地址 ...

    FINANCE接口函数

     # FINANCE()  财务数据 数组
     def GetFinance(self, symbol, id, period,right,kcount,jobID)
    

    参数说明

    symol

    股票代码

    id

    对应 FINANCE(id)

    period

    周期
    0=日线 1=周线 2=月线 3=年线 4=1分钟 5=5分钟 6=15分钟 7=30分钟 8=60分钟 9=季线 10=分笔

    right

    复权
    0=不复权 1=前复权 2=后复权

    kcount

    k线个数

    jobID

    任务id

    返回数据格式

    返回一个字典类型的数据

    单数值类型

    如:
    FINANCE(15) 流动负债,上市公司最近一期财报数据
    FINANCE(17) 资本公积金,上市公司最近一期财报数据
    都是返回最新一期财报数据
    格式
    {'type‘:0, data:数据 }

    时间序列数据

    如:
    FINANCE(1) 总股本(随时间可能有变化)
    FINANCE(7) 流通股本(随时间可能有变化)
    是一个时间序列数据, 降序排序
    格式
    {‘type’:2, data:数据数组 , date:日期数组(数值型)}

    tushare数据对接例子

    数据使用tushare的数据对接

    1. 每日指标 daily_basic, 接口文档见https://waditu.com/document/2?doc_id=32
    2. 财务指标数据 fina_indicator。 接口文档见https://waditu.com/document/2?doc_id=79
    3. 资产负债表 balancesheet。 接口文档见https://waditu.com/document/2?doc_id=36

    对接数据代码

    class TushareHQChartData(IHQData) :
    ..........................
    	# FINANCE()  财务数据 数组
        def GetFinance(self, symbol, id, period,right,kcount,jobID) :
            if (id==1) : # FINANCE(1) 总股本(随时间可能有变化)
                return self.GetDailyBasicData(symbol,"total_share")
            elif (id==7) :# FINANCE(7)  流通股本(随时间可能有变化)
                return self.GetDailyBasicData(symbol,"float_share")
            elif (id==9) : # FINANCE(9)  资产负债率 即:(总资产-净资产-少数股东权益)/总资产*100,上市公司最近一期财报数据
                return self.GetFinaIndicatorLatest(symbol,"debt_to_assets")
            elif (id==15) : # FINANCE(15) 流动负债,上市公司最近一期财报数据
                return self.GetBalanceSheetLatest(symbol,"total_cur_liab")
            elif (id==17) : # FINANCE(17) 资本公积金,上市公司最近一期财报数据
                return self.GetBalanceSheetLatest(symbol,"capital_rese_ps")
            elif (id==18) : # FINANCE(18)  每股公积金,上市公司最近一期财报数据
                return self.GetBalanceSheetLatest(symbol, "surplus_rese_ps")
            elif (id==40) : # FINANCE(40)  流通市值
                return self.GetDailyBasicDataLatest(symbol,"circ_mv")
            elif (id==43) : # FINANCE(43)  净利润同比增长率,上市公司最近一期财报数据
                return self.GetFinaIndicatorLatest(symbol,"q_profit_yoy")
            elif (id==44) : # FINANCE(44)  收入同比增长率,上市公司最近一期财报数据
                return self.GetFinaIndicatorLatest(symbol,"q_sales_yoy")
    
    	# https://waditu.com/document/2?doc_id=32
        def GetDailyBasicData(self, symbol,fieldname) :
            df=self.TusharePro.daily_basic(ts_code=symbol,start_date=str(self.StartDate), end_date=str(self.EndDate), fields='trade_date,{0}'.format(fieldname))
            df=df.sort_index(ascending=False) # 数据要降序排
            print(df)
    
            aryDate=df["trade_date"]
            aryDate[aryDate == ''] = 0
            aryDate = aryDate.astype(np.int).tolist()
    
            if (fieldname in ("total_share","float_share" )) :
                aryShare=np.multiply(df[fieldname],10000).tolist()
            else :
                aryShare=df[fieldname].tolist()
    
            result={"type": 2}  # 类型2 根据'date'自动合并到K线数据上
            result["data"]=aryShare
            result["date"]=aryDate
            return result
    
        # https://waditu.com/document/2?doc_id=32
        def GetDailyBasicDataLatest(self, symbol,fieldname):
            df=self.TusharePro.daily_basic(ts_code=symbol, trade_date=str(self.EndDate), fields='trade_date,{0}'.format(fieldname))
            print(df)
    
            result={"type": 0}  # 类型0 单值数据
            if (fieldname=='circ_mv') : # 流通市值 万元
                result["data"]=df[fieldname]*10000
            else :
                result["data"]=df[fieldname]
            return result
    
        # https://waditu.com/document/2?doc_id=79
        def GetFinaIndicatorLatest(self,symbol,fieldname):
            df = self.TusharePro.fina_indicator(ts_code=symbol)
            print(df)
    
            result={"type": 0}  # 类型0 单值数据
            if (len(df[fieldname])>0) :
                result["data"]=df[fieldname][0] # 取最新一期的数据
            else :
                result["data"]=0
            return result
    
        # https://waditu.com/document/2?doc_id=36
        def GetBalanceSheetLatest(self,symbol,fieldname):
            df = self.TusharePro.balancesheet(ts_code=symbol, fields="end_date,{0}".format(fieldname))
            print(df)
    
            result={"type": 0}  # 类型0 单值数据
            if (len(df[fieldname])>0) :
                value=df[fieldname][0]
                if (np.isnan(value)) :
                    result["data"]=0
                else :
                    result["data"]=df[fieldname][0] # 取最新一期的数据
            else :
                result["data"]=0
            return result
    

    交流QQ群

    如果有什么问题或需求可以加交流QQ群: 950092318** 联系群主(QQ48274798)

    hqchartPy动态库地址

    https://github.com/jones2000/HQChart/tree/master/C++指标计算引擎/py版本

    HQChart代码地址

    地址:https://github.com/jones2000/HQChart

    展开全文
  • hqchartPy2数据对接教程1-K线数据K线获取接口函数函数定义参数说明symolperiodrightjobID返回数据格式nameperiodrightycloseopenhighlowclosevolamounttushare数据对接例子TushareHQChartDataHQResultTest注意点K...

    K线获取接口函数

    函数定义

    class IHQData(object):
    	# K线数据
    	def GetKLineData(self, symbol, period, right, jobID) :
    

    参数说明

    symol

    股票代码

    period

    周期
    0=日线 1=周线 2=月线 3=年线 4=1分钟 5=5分钟 6=15分钟 7=30分钟 8=60分钟 9=季线 10=分笔

    right

    复权
    0=不复权 1=前复权 2=后复权

    jobID

    任务id

    返回数据格式

    返回一个字典类型的数据

    name

    股票名称 字符串

    period

    周期 数值型

    right

    复权 数值型

    yclose

    前收盘价 数值型数组

    open

    开盘价 数值型数组

    high

    最高价 数值型数组

    low

    最低价 数值型数组

    close

    收盘价 数值型数组

    vol

    成交量 数值型数组

    amount

    成交金额

    tushare数据对接例子

    使用 pro_bar 数据接口获取K线数据,接口说明见https://waditu.com/document/2?doc_id=146

    TushareHQChartData

    新建一个tushare数据类TushareHQChartData
    TusharePro tushare数据类接口
    StartDate 指标计算的起始时间
    EndDate 指标计算的结束时间

    在TushareHQChartData的构造函数中首先设置一个tushare的token, 后面就可以用tushare获取数据了。

    HQResultTest

    计算数据结果类
    指标计算结果成功/异常都是通过回调直接发送到这个类里面,可以在这个类里面保存结果数据

    class HQResultTest():
        def __init__(self):
            self.Result = []    # 保存所有的执行结果
        
         # 执行成功回调
        def RunSuccess(self, symbol, jsData, jobID):
            self.Result.append({"Symbol":symbol, "Data":jsData})  # 保存结果
            log="{0} success".format(symbol)
            print (log)
            print (jsData)
    
        # 执行失败回调
        def RunFailed(self, code, symbol, error,jobID) :
            log="{0}\n{1} failed\n{2}".format(code, symbol,error)
            print(log)
    

    注意点

    1. K线数据降序排
    2. date 日期 数值类型 格式YYYYMMDD 如: 20201012 =>2020-10-12
    3. time 时间 数值类型 格式HHMM 如 945=>9:45 , 1421=>14:21

    K数据对接代码

    class TushareHQChartData(IHQData) :
        def __init__(self, token, startDate, endDate):
            ts.set_token(token) 
            self.TusharePro = ts.pro_api()
            self.StartDate=startDate
            self.EndDate=endDate
        
        def GetKLineData(self, symbol, period, right, jobID) :
            # 复权 0=不复权 1=前复权 2=后复权
            fq=None # 复权
            if (right==1) : # 前复权
                fq="qfq"
            elif (right==2) :   # 后复权
                fq="hfq"
    
            # 周期 0=日线 1=周线 2=月线 3=年线 4=1分钟 5=5分钟 6=15分钟 7=30分钟 8=60分钟 9=季线 10=分笔
            freq='D'
            if (period==1) :
                freq="W"
            elif (period==2):
                freq="M"
            elif (period==4):
                freq="1MIN"
            elif (period==5):
                freq="5MIN"
            elif (period==6):
                freq="15MIN"
            elif (period==7):
                freq="30MIN"
            elif (period==8):
                freq="60MIN"
    
            df = ts.pro_bar(ts_code=symbol, adj=fq, start_date=str(self.StartDate), end_date=str(self.EndDate),freq=freq)
            # df = self.TusharePro.daily(ts_code=symbol, start_date='20200101', end_date='20201231')
            df=df.sort_index(ascending=False) # 数据要降序排
            print(df)
    
            cacheData={}
            if (period in (0,1,2,3,9)) :
                # 日期转int
                aryDate=df["trade_date"]
                aryDate[aryDate == ''] = 0
                aryDate = aryDate.astype(np.int)
                dataCount=len(aryDate) 
                cacheData['count']=dataCount    # 数据个数
                cacheData["date"]=aryDate.tolist()
            else :
                aryDateTime=df["trade_time"]
                dataCount=len(aryDateTime) 
                cacheData['count']=dataCount    # 数据个数
                aryDateTime= pd.to_datetime(aryDateTime, format="%Y-%m-%d %H:%M:%S")
                print(aryDateTime)
                aryDate=[]
                aryTime=[]
                for item in aryDateTime :
                    aryDate.append(item.year*10000 + item.month* 100  + item.day)
                    aryTime.append(item.hour*100+item.minute)
                cacheData["time"]=aryTime
                cacheData["date"]=aryDate
    
            
            cacheData['name']=symbol        # 股票名称
            cacheData['period']=period      # 周期
            cacheData['right']=period       # 不复权
    
            cacheData["yclose"]=np.array(df["pre_close"]).tolist()
            cacheData["open"]=np.array(df["open"]).tolist()
            cacheData["high"]=np.array(df["high"]).tolist()
            cacheData["low"]=np.array(df["low"]).tolist()
            cacheData["close"]=np.array(df["close"]).tolist()
            cacheData["vol"]=np.array(df["vol"]).tolist()
            cacheData["amount"]=np.array(df["amount"]).tolist()
            
            log="K线:{0} - period={1} right={2} count={3}".format(symbol,period,right,dataCount)
            print(log)
    
            return cacheData
    

    **注意:分钟数据没有测试过,因为tushare分钟数据需要付费购买,如果有朋友提供账户,我可以把分钟数据的例子也加上 **

    测试脚本

    def TestSingleStock() :
        # 授权码
        key="授权码"
        FastHQChart.Initialization(key)
    
        runConfig={
            # 系统指标名字
            # "Name":"MA",
            "Script":'''
            T:MA(C,M1);
            T2:MA(C,M2);
            T3:MA(C,M3);
            ''',
            # 脚本参数
            "Args": [ { "Name":"M1", "Value":15 }, { "Name":"M2", "Value":20 }, { "Name":"M3", "Value":30} ],
            # 周期 复权
            "Period":0, "Right":1,
            "Symbol":"600000.sh",
    
            #jobID (可选)
            "JobID":"1234-555-555"
        }
    
        jsConfig = json.dumps(runConfig)    # 运行配置项
        hqData=TushareHQChartData("tushare的token",startDate=20200421, endDate=20201231)    # 实例化数据类
        result=HQResultTest()   # 实例计算结果接收类
    
        start = time.process_time()
    
        res=FastHQChart.Run(jsConfig,hqData,proSuccess=result.RunSuccess, procFailed=result.RunFailed)
    
        elapsed = (time.process_time() - start)
        log="TestSingleStock() Time used:{0}, 股票{1}".format(elapsed, runConfig['Symbol'])
        print(log)
    

    数据结果截图

    在这里插入图片描述

    交流QQ群

    如果有什么问题或需求可以加交流QQ群: 950092318** 联系群主(QQ48274798)

    hqchartPy动态库地址

    https://github.com/jones2000/HQChart/tree/master/C++指标计算引擎/py版本

    HQChart代码地址

    地址:https://github.com/jones2000/HQChart

    展开全文
  • 图纸数据对接格式

    2019-03-06 16:00:57
    图纸数据对接格式 通过读取板材上的条码信息从客户数据库中读取对应图纸,而后对该图纸进行解析,解析返回的数据参考如下格式(字符型数组,一行为一字符组员) ...

    图纸数据对接格式

    通过读取板材上的条码信息从客户数据库中读取对应图纸,而后对该图纸进行解析,解析返回的数据参考如下格式(字符型数组,一行为一字符组员)

    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • 如何高效简洁的完成OushuDB与Greenplum之间数据对接GP集群间对接方案优点方案缺点OushuDB架构OushuDB与GP对接 最近有项目需要做偶数云原生数据库(后简称:OushuDB)与Greenplum(后简称:GP)之间数据对接。主要背景是...
  • MQTT数据对接相关文献

    2021-06-15 14:00:13
    MQTT数据对接相关文献 1. 基于HTTP/2通道的服务端订阅-设备状态和数据 https://www.yuque.com/cloud-dev/iot-tech/cev3cn 2. 阿里云物联网平台设备日志上报示例Demo https://developer.aliyun.com/article/757198 ...
  • 10-9 View数据对接

    2020-10-09 18:41:42
    PDI部署流程一、PDI对接测试(本地测试)二、下载PDI对接包三、PDI对接-转换同步调用关系四、PDI医嘱数据对接(本地测试) 一、PDI对接测试(本地测试) 二、下载PDI对接包 从gitlab上下载PDI对接包,下载地址:...
  • HQChart实战教程10-全ws数据对接HQChart(火币网数据对接实战需求第3方数据接口一分钟历史k线最新一分钟K线数据订阅对接步骤1. 取消hqchart自动更新2. 设置NetworkFilter回调3. NetworkFilter4. 简单的封装下ws数据...
  • 简单的webservice+Cxf+Spring数据对接实例以及jar.rar简单的webservice+Cxf+Spring数据对接实例以及jar.rar简单的webservice+Cxf+Spring数据对接实例以及jar.rar简单的webservice+Cxf+Spring数据对接实例以及jar.rar...
  • 移动广告平台力美多盟点入 iOS广告主APP敷活数据对接 上海泽思网络科技有限公司 更新时间:2013-10-15 TOC \o "1-5" \h \z \o "Current Document" 一 力美APP激活数据对接 3 \o "Current Document" 目的 3 \o ...
  • 通过今天的学习,我学习了vue的数据对接,分页显示,登录配置以及数据绑定,并克隆团队仓库,进行协同开发。 通过课后的回顾,我总结了这次学习中的几个重要知识点: 数据对接 .env.development:开发时配置文件 ....
  • 多盟iOS广告主APP激活数据对接
  • hqchartPy2数据对接教程2-股本数据,筹码分布函数总股本获取接口函数流通股本获取接口函数历史流通股本获取接口函数参数说明symolperiodrightkcountjobID返回数据格式单数值类型时间序列数据tushare数据对接例子交流...
  • 数据对接-ETL之StreamSet学习之旅六

    千次阅读 热门讨论 2019-03-06 11:09:38
    StreamSet作为大数据ETL工具的选择,当然需要处理数据的合并与转存,这里介绍针对mysql数据库的同步转存,采用mysql的binary Log方式进行。 学习系列 数据对接-ETL之StreamSet学习之旅一 ... 数据对接-E...
  • PZEM-004T-100A 交流通讯盒数据对接 JAVA 使用maven 主要看启动类,完全可以使用
  • 一个商城系统和多个卖家系统 现在需要做卖家在商城中有了新的订单时 在该卖家系统中也生成一条订单信息 这个数据对接的过程需要用啥技术解决 给点思路
  • 本人是做软件实施工程师 今天经理说让我搞数据库数据对接,因为本公司是做库房管理 就是wms 然后要与erp那面的数据对接 商品信息 下的单子信息等等数据库数据,有点蒙,求指教 这个数据库如何操作对接数据 说是用...
  • hqchartPy2数据对接教程3-DYNAINFO函数DYNAINFO()接口函数参数说明symolidperiodrightkcountjobID返回数据格式tushare数据对接例子交流QQ群hqchartPy动态库地址HQChart代码地址 DYNAINFO() 即时行情数据 DYNAINFO(3)...
  • 钉钉考勤接口调用与OA系统数据对接

    千次阅读 2019-11-18 11:32:10
    钉钉考勤接口调用与OA系统数据对接 公司由原来的指纹打卡更换为钉钉打卡,需要钉钉和现有的OA考勤数据对接(合并钉钉打卡数据和OA上的请假,外出,出差数据) 1.查看钉钉接口文档 ... 2.项目搭建引入钉钉开发SDK ...
  • 摘要: 需求: 你有没有遇到过不同数据库之间数据对接的需求,比如:mysql数据库里的数据要保存到oracle数据库里,或者是excel里的数据要保存到数据库里,或者是数据库的数据要定时的保存到文件中等等数据对接的...
  • java实现JT809协议数据对接客户端

    万次阅读 热门讨论 2016-10-13 14:16:10
    最近使用JT809协议进行数据对接,遇到了不少问题,度娘谷歌都不好使,找不到很好的客户端实现代码的例子,只能苦逼的自己闷头弄,现在特意写篇帖子,希望能帮助一些人 说正经的: 背景:跟某公司做数据对接,将本...
  • 线上平台与线下某些软件系统要实现数据对接和数据互传,并且不能影响软件系统的正常运行。            其实很多互联网产品中都这样的需求,很多平台运营商吸引线下商家、客户...
  • 数据对接—kettle使用之一

    千次阅读 2018-03-20 17:36:50
    转载自:https://yq.aliyun.com/articles/38089?spm=a2c4e.11163080.searchblog.28.1a6a2ec1P1lHzh需求: 你有没有遇到过不同数据库之间数据对接的需求,比如:mysql数据库里的数据要保存到oracle数据库里,或者是...
  • HQChart实战教程13-火币网ws数据对接K线uniapp版本效果图对接步骤uniapp websockethqchart设置数据完整代码HQChart代码地址 效果图 对接步骤 对接步骤和VUE对接是一致的。这里我就不多说了。具体可以看上一节教程...
  • 很多朋友咨询过我,说怎么能够设置StreamSets为定时启动模式,或者定时干某件事,我都很肯定的告诉他,StreamSets不是这么用的,它一旦启动,就会一直跑,只能设定采集速度模糊控制时间。...数据对接.
  • HQMS医院质量管理监测系统数据对接接口标准

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 10,162
精华内容 4,064
关键字:

数据对接