22.项目开发之量化交易抓取数据QuantTradeData(一)

news2024/11/19 5:34:01

项目创建及后端业务:定时更新“股票列表基础信息”数据

项目创建

该量化交易数据平台用于数据库的数据抓取、分析等操作。
和QuantTrade使用同一个数据库,无需重新创建

01
02
03
04
pom.xml


<properties>
   <java.version>1.8</java.version>
   <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
   <spring-boot.version>2.3.12.RELEASE</spring-boot.version>
</properties>
<dependencies>
   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-web</artifactId>
   </dependency>
   <dependency>
       <groupId>org.mybatis.spring.boot</groupId>
       <artifactId>mybatis-spring-boot-starter</artifactId>
       <version>2.2.2</version>
   </dependency>
   <dependency>
       <groupId>mysql</groupId>
       <artifactId>mysql-connector-java</artifactId>
       <version>8.0.33</version>
   </dependency>
   <dependency>
       <groupId>org.projectlombok</groupId>
       <artifactId>lombok</artifactId>
       <optional>true</optional>
   </dependency>
   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-test</artifactId>
       <scope>test</scope>
       <exclusions>
           <exclusion>
               <groupId>org.junit.vintage</groupId>
               <artifactId>junit-vintage-engine</artifactId>
           </exclusion>
       </exclusions>
   </dependency>
   <dependency>
       <groupId>io.springfox</groupId>
       <artifactId>springfox-boot-starter</artifactId>
       <version>3.0.0</version>
   </dependency>
   <dependency>
       <groupId>com.alibaba</groupId>
       <artifactId>fastjson</artifactId>
       <version>1.2.17</version>
   </dependency>
   <dependency>
       <groupId>com.opencsv</groupId>
       <artifactId>opencsv</artifactId>
       <version>5.7.1</version>
   </dependency>
   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-quartz</artifactId>
   </dependency>
</dependencies>
<dependencyManagement>
   <dependencies>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-dependencies</artifactId>
           <version>${spring-boot.version}</version>
           <type>pom</type>
           <scope>import</scope>
       </dependency>
   </dependencies>
</dependencyManagement>

<build>
   <plugins>
       <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-compiler-plugin</artifactId>
           <version>3.8.1</version>
           <configuration>
               <source>1.8</source>
               <target>1.8</target>
               <encoding>UTF-8</encoding>
           </configuration>
       </plugin>
       <plugin>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-maven-plugin</artifactId>
           <version>${spring-boot.version}</version>
           <configuration>
               <mainClass>com.quanttrade_bk.QuantTradeBkApplication</mainClass>
               <skip>true</skip>
           </configuration>
           <executions>
               <execution>
                   <id>repackage</id>
                   <goals>
                       <goal>repackage</goal>
                   </goals>
               </execution>
           </executions>
       </plugin>
   </plugins>
</build>


05

application.properties


# 应用服务 WEB 访问端口
server.port=8082
# 配置数据库连接信息
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3380/db_quant?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=1234
#配置mapper.xml的路径
mybatis.mapper-locations=classpath:mapper/*/*.xml


Application

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@SpringBootApplication
@EnableSwagger2
public class QuantTradeDataApplication {

   public static void main(String[] args) {
       SpringApplication.run(QuantTradeDataApplication.class, args);
   }
   /**
    * 向spring注册RestTemplate工具
    * @return
    */
   @Bean
   public RestTemplate getRestTemplate(){
       return new RestTemplate();
   }
}


06

RestObject

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class RestObject {
   private Integer code;           //前端的状态码 0:业务失败  1:业务成功
   private String msg;              //前端需要展示的信息
   private Object data;            //前端需要的复杂数据
   //业务成功的方法----------
   /**
    * 业务成功,自定义返回msg和返回的数据
    * @param msg
    * @param data
    * @return
    */
   public static RestObject OK(String msg,Object data){
       return new RestObject(1,msg,data);
   }
   /**
    * 业务成功,自定义返回msg,无返回数据
    * @param msg
    * @return
    */
   public static RestObject OK(String msg){
       return OK(msg,null);
   }
   /**
    * 业务成功,自定义返回的数据,无返回msg
    * @param data
    * @return
    */
   public static RestObject OK(Object data){
       return OK(null,data);
   }
   //业务失败的方法----------
   /**
    * 业务失败,自定义返回msg和返回的数据
    * @param msg
    * @param data
    * @return
    */
   public static RestObject ERROR(String msg,Object data){
       return new RestObject(0,msg,data);
   }
   /**
    * 业务失败,自定义返回msg,无返回数据
    * @param msg
    * @return
    */
   public static RestObject ERROR(String msg){
       return ERROR(msg,null);
   }
   /**
    * 业务失败,自定义返回的数据,无返回msg
    * @param data
    * @return
    */
   public static RestObject ERROR(Object data){
       return ERROR(null,data);
   }
}


搭建Const和TuShareAPI工具
07
Const

public interface Const {
   //平台地址
   String TUSHARE_BASE_URL     =   "http://api.tushare.pro";
   //令牌
   String TUSHARE_TOKEN        =   "自己的token";
   //股票基本信息
   String STOCK_BASIC = "stock_basic";
   //股票日线基本行情
   String STOCK_DAILY = "daily";
}



import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class TuShareAPI {
   @Autowired
   RestTemplate template;
   /**
    * 用于向tushare平台发送请求,并接收到响应
    * @param api
    * @param params
    * @param fields
    * @return
    */
   public JSONObject get(String api, Map<String, String> params, List<String> fields) {
       Map<String, Object> allParam = new HashMap<>();
       allParam.put("api_name", api);
       allParam.put("token", Const.TUSHARE_TOKEN);
       // 请求参数
       allParam.put("params", params);
       // 设置 需要响应回来的字段
       if (fields != null && fields.size()>0) {
           StringBuffer buffer = new StringBuffer();
           int size = fields.size();
           for (int i = 0; i <size; i++) {
               buffer.append(fields.get(i));
               if(i!=size-1){
                   buffer.append(",");
               }
           }
           allParam.put("fields", buffer.toString());
       }
       //设置并发送请求,获取并返回响应
       HttpHeaders headers = new HttpHeaders();
       headers.setContentType(MediaType.APPLICATION_JSON);
       HttpEntity<Map> entity = new HttpEntity<>(allParam, headers);
       String str = template.postForObject(Const.TUSHARE_BASE_URL,entity, String.class);
       JSONObject json = JSON.parseObject(str);
       return json;
   }
}

08

启动时,运行: http://localhost:8082/swagger-ui/index.html

09

后端业务:定时更新“股票列表基础信息”数据

需求说明

为了获取前一天的最新数据,我们需要每个工作日的晚上10点定时刷新stock_basic股票列表基础信息,并将最新数据插入或更新到数据库中,将已经退市的数据删除。

前置知识:Quartz定时框架

Apache提供定时框架Quartz来帮助我们进行定时任务。

依赖

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

其中作业:Job (其中去编写要执行的任务)
作业详情:JobDetail (对任务属性进行调整)
触发器:Trigger(负责执行具体的某个作业)都是执行任务必不可少的组件。

我们将需要执行的任务写入Job,并通过JobBuilder来构建JobDetail。
通过TriggerBuilder来构建触发器,并加入任务与执行周期&频率,让任务执行。
其中,Cron表达式无需独立学习,通过在线构建即可:https://cron.qqe2.com/

Job:

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;

import java.util.Date;

public class TestJob1 extends QuartzJobBean {
   @Override
   protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
       //定时去做什么事情
       System.out.println("TestJob1:"+new Date().toLocaleString());
   }
}

任务配置:


import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class QuartzConfig {

   /**
    * 构建任务详情
    * @return
    */
   @Bean
   public JobDetail getTestJob1(){
       //1、通过构建,获取任务详情并返回
       //storeDurably()  脱离Trigger进行独立保存
       return JobBuilder.newJob(TestJob1.class).storeDurably().build();
   }

   @Bean
   public Trigger getTestJob1Trigger(JobDetail getTestJob1){
       //1、创建Cron表达式
       //1秒执行一次
//        CronScheduleBuilder cron = CronScheduleBuilder.cronSchedule("* * * * * ?");
       //从00秒开始  每10秒执行一次
       CronScheduleBuilder cron = CronScheduleBuilder.cronSchedule("0/10 * * * * ? ");
       //2、通过构建,完成触发器的创建并返回
       return TriggerBuilder.newTrigger().forJob(getTestJob1).withSchedule(cron).build();
   }
}


案例:定时点名 每秒定时抽一个学生姓名

1、创建一个Job,读取txt里的数据,随机获取其中一个

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.util.ResourceUtils;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class RandomNameJob extends QuartzJobBean {
   private static List<String> names = new ArrayList<>();
   static {
       //读取txt获取数据
       //获取file文件
       File file;
       try {
           file = ResourceUtils.getFile("classpath:test.txt");
       } catch (FileNotFoundException e) {
           throw new RuntimeException(e);
       }
       //获取缓冲字符流
       try (BufferedReader reader = new BufferedReader(new FileReader(file));){
           //读取数据,保存到names
           String line = null;
           while ((line=reader.readLine())!=null){
               names.add(line);
           }
       } catch (FileNotFoundException e) {
           throw new RuntimeException(e);
       } catch (IOException e) {
           throw new RuntimeException(e);
       }
   }
   private static Random r = new Random();
   @Override
   protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
       System.out.println("随机点名:"+names.get(r.nextInt(names.size())));
   }
}

2、创建JobDetail,创建Trigger 给于cron

import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class QuartzConfig {

   /**
    * 构建任务详情
    * @return
    */
   @Bean
   public JobDetail getTestJob1(){
       //1、通过构建,获取任务详情并返回
       //storeDurably()  脱离Trigger进行独立保存
       return JobBuilder.newJob(TestJob1.class).storeDurably().build();
   }

   @Bean
   public Trigger getTestJob1Trigger(JobDetail getTestJob1){
       //1、创建Cron表达式
       //1秒执行一次
//        CronScheduleBuilder cron = CronScheduleBuilder.cronSchedule("* * * * * ?");
       //从00秒开始  每10秒执行一次
       CronScheduleBuilder cron = CronScheduleBuilder.cronSchedule("0/10 * * * * ? ");
       //2、通过构建,完成触发器的创建并返回
       return TriggerBuilder.newTrigger().forJob(getTestJob1).withSchedule(cron).build();
   }

   /**
    * 构建任务详情
    * @return
    */
   @Bean
   public JobDetail getRandomNameJob(){
       //1、通过构建,获取任务详情并返回
       //storeDurably()  脱离Trigger进行独立保存
       return JobBuilder.newJob(RandomNameJob.class).storeDurably().build();
   }

   @Bean
   public Trigger getRandomNameJobTrigger(JobDetail getRandomNameJob){
       //1、创建Cron表达式
       //1秒执行一次
       CronScheduleBuilder cron = CronScheduleBuilder.cronSchedule("* * * * * ?");
       //2、通过构建,完成触发器的创建并返回
       return TriggerBuilder.newTrigger().forJob(getRandomNameJob).withSchedule(cron).build();
   }
}

股票列表基础信息表(tb_stock_basic_info)

09

股票列表基础信息实体(StockBasicInfo)

10
11

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class StockBasicInfo {
   private String tscode;          //TS代码
   private String stockcode;    //股票代码
   private String stockname;   //股票名称
   private String stockarea;     //地域
   private String industry;       //所属行业
   private String cnspell;         //拼音缩写
   private String market;         //市场类型
   private String list_date;       //上市日期
   private String is_hs;            //是否沪深港通标的,N否 H沪股通 S深股通
   private String op_date;       //操作日期  yyyy-MM-dd
}

三层搭建

12

13
StockBasicInfoMapper


import org.springframework.stereotype.Repository;

@Repository
public interface StockBasicInfoMapper {
}

Application

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@SpringBootApplication
@EnableSwagger2
@MapperScan("com.quanttradedata.stock.mapper")
public class QuantTradeDataApplication {

   public static void main(String[] args) {
       SpringApplication.run(QuantTradeDataApplication.class, args);
   }
   /**
    * 向spring注册RestTemplate工具
    * @return
    */
   @Bean
   public RestTemplate getRestTemplate(){
       return new RestTemplate();
   }
}


StockBasicInfoMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
       PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
       "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.quanttradedata.stock.mapper.StockBasicInfoMapper">

</mapper>

StockService


import com.quanttradedata.stock.mapper.StockBasicInfoMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class StockService {
   @Autowired
   private StockBasicInfoMapper stockBasicInfoMapper;
}

StockController


import com.quanttradedata.stock.service.StockService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/stock")
@CrossOrigin //跨域在开发环境可以有,在生产环境中尽可能去除
public class StockController {
   @Autowired
   private StockService stockService;
}


业务实现

StockBasicInfoJob


import com.quanttradedata.stock.service.StockService;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;

@Component
public class StockBasicInfoJob extends QuartzJobBean {
   @Autowired
   private StockService stockService;
   private SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");

   @Override
   protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
       //1、准备需要传递给tuShare 参数
       HashMap<String, String> param = new HashMap<>();
       param.put("exchange","SSE");
       param.put("list_status","L");
       //2、请求 SSE上交所的股票基本信息
       System.out.println("请求SSE上交所的股票基本信息......");
       stockService.saveStockBasicInfoFromNet(param);
       //3、请求 SZSE深交所的股票基本信息
       System.out.println("请求 SZSE深交所的股票基本信息......");
       param.put("exchange","SZSE");
       stockService.saveStockBasicInfoFromNet(param);
       //4、数据更新完毕,删除退市失效数据
       stockService.delStockBasicInfosByOpDate(sdf1.format(new Date()));
   }
}


QuartzConfig


import com.quanttradedata.stock.job.StockBasicInfoJob;
import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class QuartzConfig {
   //股票基本信息的 任务详情创建 及 触发器创建
   @Bean
   public JobDetail getStockBasicInfoJob(){
       return JobBuilder.newJob(StockBasicInfoJob.class).storeDurably().build();
   }
   @Bean
   public Trigger getStockBasicInfoJobTrigger(JobDetail getStockBasicInfoJob){
       //1、编写cron表达式,指定触发的时间和周期
       //开发执行: 每个工作日的晚上22点
       //CronScheduleBuilder cron = CronScheduleBuilder.cronSchedule("0 0 22 ? * MON-FRI");
       //测试执行: 每5秒执行一次
       CronScheduleBuilder cron = CronScheduleBuilder.cronSchedule("0/5 * * * * ? ");
       //2、构建触发器,执行任务
       return TriggerBuilder.newTrigger().forJob(getStockBasicInfoJob).withSchedule(cron).build();
   }
}


StockService


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.quanttradedata.stock.javabean.StockBasicInfo;
import com.quanttradedata.stock.mapper.StockBasicInfoMapper;
import com.quanttradedata.utils.javabean.Const;
import com.quanttradedata.utils.javabean.TuShareAPI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.SQLIntegrityConstraintViolationException;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class StockService {
   @Autowired
   private StockBasicInfoMapper stockBasicInfoMapper;
   @Autowired
   private TuShareAPI tuShareAPI;
   private SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
   /**
    * 根据参数,请求并更新股票列表信息
    * @param param
    */
   public void saveStockBasicInfoFromNet(HashMap<String, String> param) {
       //1、指定TuShare平台需要给项目返回哪些字段数据
       List<String> fields = new ArrayList<>();
       Collections.addAll(fields,
               "ts_code","symbol","name","area","industry","cnspell","market","list_date","is_hs");
       //2、向TuShare平台发请求,请求json数据
       JSONObject jsonObject = tuShareAPI.get(Const.STOCK_BASIC, param, fields);
       //3、解析json数据,转为List集合
       List<StockBasicInfo> stockBasicInfos = new ArrayList<>();
       //3.1、获取所有的行数据
       JSONArray jsonArray = jsonObject.getJSONObject("data").getJSONArray("items");
       //3.2、遍历每行数据,每行转为一个StockBasicInfo对象
       Date today = new Date();
       String todayStr = sdf1.format(today);
       for (int i = 0; i < jsonArray.size(); i++) {
           JSONArray array = jsonArray.getJSONArray(i);
           //3.3、将StockBasicInfo对象保存到List中
           stockBasicInfos.add(
                   new StockBasicInfo(
                           array.getString(0),
                           array.getString(1),
                           array.getString(2),
                           array.getString(3),
                           array.getString(4),
                           array.getString(5),
                           array.getString(6),
                           array.getString(7),
                           array.getString(8),
                           todayStr
                   )
           );
       }
       //4、进行数据插入或更新操作
       int insertCount=0,updateCount=0;
       //插入或更新
       if(stockBasicInfos.size()>0){
           //有需要插入或更新的数据,开始更新
           for (StockBasicInfo sbi : stockBasicInfos) {
               try {
                   int rows = stockBasicInfoMapper.insertStockBasicInfo(sbi);
                   insertCount+=rows;
               } catch (Exception e) {
                   //1、判断是否为SQLIntegrityConstraintViolationException类型的异常
                   if(e.getCause() instanceof SQLIntegrityConstraintViolationException){
                       //2、如果是该类型,判断是否为重复主键错误
                       String errorMsg = e.getMessage();
                       //System.out.println(errorMsg);
                       if(errorMsg.contains("Duplicate entry") && errorMsg.contains("PRIMARY")){
                           //3、如果是重复主键错误,说明该数据,数据库已经存在了,没必要在Insert,进行该数据的update 即可
                           int rows = stockBasicInfoMapper.updateStockBasicInfo(sbi);
                           updateCount+=rows;
                       }
                   }
               }
           }
       }
       //5、展示结果
       System.out.println("插入成功了"+insertCount+"条数据");
       System.out.println("更新成功了"+updateCount+"条数据");
   }

   /**
    * 根据今天日期,删除不是今天数据的退市数据
    * @param todayStr
    */
   public void delStockBasicInfosByOpDate(String todayStr){
       //更新完毕后,已经退市的数据要从数据库删除掉
       int delCount = stockBasicInfoMapper.delStockBasicInfosByOpDate(todayStr);
       System.out.println("删除成功了"+delCount+"条失效数据");
   }
}

StockBasicInfoMapper


import com.quanttradedata.stock.javabean.StockBasicInfo;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;

@Repository
public interface StockBasicInfoMapper {
   /**
    * 添加一条股票基本信息
    * @param sbi
    * @return
    */
   int insertStockBasicInfo(@Param("sbi") StockBasicInfo sbi);

   /**
    * 更新一条股票基本信息
    * @param sbi
    * @return
    */
   int updateStockBasicInfo(@Param("sbi") StockBasicInfo sbi);

   /**
    * 删除不是今天的股票基本信息(删除退市数据)
    * @param todayStr
    * @return
    */
   int delStockBasicInfosByOpDate(@Param("todayStr")String todayStr);
}

StockBasicInfoMapper.xml


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
       PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
       "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.quanttradedata.stock.mapper.StockBasicInfoMapper">
   <insert id="insertStockBasicInfo">
       insert into tb_stock_basic_info values (
                                       #{sbi.tscode},
                                       #{sbi.stockcode},
                                       #{sbi.stockname},
                                       #{sbi.stockarea},
                                       #{sbi.industry},
                                       #{sbi.cnspell},
                                       #{sbi.market},
                                       #{sbi.list_date},
                                       #{sbi.is_hs},
                                       #{sbi.op_date}
                                              )
   </insert>
   <update id="updateStockBasicInfo">
       update tb_stock_basic_info set
           stockname=#{sbi.stockname},
           stockarea=#{sbi.stockarea},
           industry=#{sbi.industry},
           cnspell=#{sbi.cnspell},
           market=#{sbi.market},
           list_date=#{sbi.list_date},
           is_hs=#{sbi.is_hs},
           op_date=#{sbi.op_date}
       where stockcode = #{sbi.stockcode}
   </update>
   <delete id="delStockBasicInfosByOpDate">
       delete from tb_stock_basic_info where op_date!=#{todayStr}
   </delete>
</mapper>

后端业务:定时更新“股票列表基础信息”数据业务完成!!!
下篇进入项目开发之量化交易抓取数据QuantTradeData(二):后端业务之定时更新“A股日线行情”数据—传送门

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1105795.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

GPU 驱动下载记录

1. 我的GPU 是这个&#xff1a;GeForce RTX 2060 下载链接是&#xff1a;Official Drivers | NVIDIA

人脸识别技术是什么?如何进行人脸识别数据标注?

人脸识别解锁、人脸识别防盗系统、人脸识别登陆账户&#xff0c;相比于传统的指纹识别或者是虹膜识别等生物识别技术&#xff0c;人脸识别的应用更加广泛和多样。人脸识别技术是什么&#xff1f;人脸识别和数据标注有什么关系&#xff1f;阅读本文你会了解&#xff1a; 人脸识…

异形led显示屏调试步骤

调试异形LED显示屏需要一定的专业知识和技能。以下是一般的异形LED显示屏调试步骤&#xff1a; 安装和连接&#xff1a; 安装LED模块和框架&#xff0c;确保它们正确固定和对齐。连接电源和信号线。确保电源供电正常&#xff0c;信号线连接正确。什么是LED显示模块&#xff1f;…

android源码查阅连接

原文链接如下&#xff1a; AOSPXRef 在此做个笔记

Paypal提现到万里汇再提现到支付宝的全过程

因为外汇管制的缘故&#xff0c;paypal的钱无法直接提现到国内银行卡。即使提现也会接到电话通知表示非常抱歉无法入账。之前还被银行主管问到是否能提供合同&#xff0c;交易信息&#xff0c;是否完税等等。因为他们对网商都不是太懂&#xff0c;知道paypal已经算不错了。但是…

【数据结构】队列-Queue

⭐ 作者&#xff1a;小胡_不糊涂 &#x1f331; 作者主页&#xff1a;小胡_不糊涂的个人主页 &#x1f4c0; 收录专栏&#xff1a;浅谈数据结构 &#x1f496; 持续更文&#xff0c;关注博主少走弯路&#xff0c;谢谢大家支持 &#x1f496; 队列 1.什么是队列2. 队列的使用3. …

报名倒计时 | 超硬核!第四届中国云计算基础架构开发者大会邀你参会

编者按&#xff1a;第四届 CID 大会将于 10 月 21 日在深圳南山科技园希尔顿花园酒店举办&#xff01;龙蜥社区作为本次 CID 大会支持的单位&#xff0c;诚邀您参与此次大会。 本大会将聚焦业界最前沿的云计算基础架构技术成果&#xff0c;围绕基础架构技术领域的技术交流&…

访问文件夹

访问文件夹并读取文件内容 将展示如何使用 JavaScript 中的 showDirectoryPicker() 方法来访问文件夹&#xff0c;并读取文件的内容。 HTML 结构 首先&#xff0c;需要一个按钮来触发打开文件夹的操作&#xff1a; <button>打开文件夹</button>还需要一个段落元…

限频差分探头N2060Apro

N2060Apro 差分探头提供一个安全的仪器给所有的示波器使用&#xff0c;它可以转换由高输入的差动电压进入一个低电压(≤7V)&#xff0c;并且显示波形在示波器上&#xff0c;使用频宽高达 200MHz&#xff0c;非常适合大电力测试、研发、维修使用。差分探头输出标示是设计在操作示…

系统大前端学习路线

第一阶段&#xff1a;HTML/CSS3以及工具部分 HTML和CSS用来制作网页&#xff0c;利用盒子模型&#xff0c;浮动&#xff0c;定位&#xff0c;flex布局进行网页布局&#xff0c;网页颜色&#xff0c;字体&#xff0c;背景&#xff0c;变换&#xff0c;过渡&#xff0c;动画等增…

flutter 创建插件

资料&#xff1a; flutter与原生通信的方式简介 - 简书 完整流程 Flutter 集成 Golang 多语言跨端开发基础案例 - 知乎 https://www.cnblogs.com/webabcd/p/flutter_lib_plugin_plugin_ios.html 步骤1、创建插件 我创建的插件名字是konnect_im_sdk 选择的语言是 java和swi…

怎么多号发圈和批量加好友?

你知道怎么多号发圈和批量加好友吗&#xff1f; 我们都知道&#xff0c;微信号多&#xff0c;管理起来是一件相当麻烦的事。 那发圈和加好友&#xff0c;多号的话&#xff0c;那是相当大的工作量&#xff0c;那有没有什么办法可以多号同时进行发圈和加人吗&#xff1f; 当然有的…

【Java实战】Mybatis plus根据数据库表自动生成代码

首先生成一个maven项目&#xff0c;不会生成的参考 【Java实战】创建第一个Springboot项目Hello worldhttps://blog.csdn.net/forgetmiss/article/details/133889733 &#xff08;写的过程中遇到过的问题&#xff1a;mybatis-plus 生成controller中的代码&#xff0c; Reques…

Bootstrap-- 内容

Bootstrap4 - 中文文档 - 内容 处理不同尺寸下的图片的处理&#xff0c;避免资源浪费&#xff01;&#xff01;&#xff01;

liunx下软链接和硬链接的用法

什么是软链接&#xff08;类似快捷方式&#xff09;&#xff1a; 符号连接&#xff08;Symbolic Link&#xff09;&#xff0c;也叫软连接。 软链接文件有类似于 Windows 的快捷方式。它实际上是一个特殊的文件。在符号连接中&#xff0c;文件实际上是一个文本文件&#xff0c…

怎么压缩证件照到200k以下?教你在线压缩图片指定kb

新一年的国考报名开始了&#xff0c;相信许多小伙伴还在发愁报名信息资料上传的问题&#xff0c;比如提交证件照时会要求具体的图片kb大小&#xff0c;本文就来教大家怎么快速图片压缩指定大小&#xff08;https://www.yasuotu.com/imagesize&#xff09;&#xff0c;而且还不需…

GitKraken for Mac:强大且跨平台的Git客户端

如果你正在寻找一个强大、直观且跨平台的Git客户端&#xff0c;那么GitKraken绝对值得你考虑。在本文中&#xff0c;我们将详细介绍GitKraken的各项功能和优势&#xff0c;以帮助你了解它如何帮助你更有效地管理和提交代码。 GitKraken是一款真正的跨平台工具&#xff0c;可以在…

2024年关于湖北省建筑安全员B证报考你需要了解

2024年关于湖北省建筑安全员B证报考你需要了解 建筑安全员B证指的是建设厅三类人员建安B证&#xff0c;很多人对于B证报考不是很了解&#xff0c;对于安全员B报考条件、报考流程、报考时间、报考地区等事项叙后尘告诉你们。 湖北建筑安全员B证报考条件-建安B证 1.你的二级建造师…

(2022|ECCV,文本图像视频,3D 邻域注意,3D 稀疏注意)NÜWA:神经视觉世界创建的视觉合成预训练

NWA: Visual Synthesis Pre-training for Neural visUalWorld creAtion 公众号&#xff1a;EDPJ&#xff08;添加 VX&#xff1a;CV_EDPJ 或直接进 Q 交流群&#xff1a;922230617 获取资料&#xff09; 目录 0. 摘要 1. 简介 2. 相关工作 2.1. 视觉自回归模型 2.2. 视觉…

HugeGraph1.0.0部署,吐槽一下Hubble的数据导入 Bug

背景 HugeGraph 安装部署了最新版本1.0.0&#xff0c;发现它的 Web 工具 Hubble 有一个大 Bug。数据导入的时候&#xff0c;配置节点属性映射这个选项时&#xff0c;下拉框只有一个选项&#xff0c;但实际上&#xff0c;元数据配置中的属性有3个&#xff0c;这个 Bug 是怎么产…