股票数据分析

前面我们介绍了Spark 和 Spark SQL,今天我们就使用 Spark SQL来分析一下我们的数据,今天我们主要分析一下股票数据

数据准备

交易数据

我们拿到了最近几年的交易数据

股票数据分析_sql

下面是具体的数据格式,csv 文件,ts_code 对于的是一个股票代码

股票数据分析_数据_02

股票详情数据

股票数据分析_big data_03

日期数据

因为股票市场不是天天开的,只有交易日才开门,下面就是我们的交易日数据

股票数据分析_spark_04

数据分析

当然这里我们的分析并不是教大家去怎么买卖股票,我们的目标是为了学习Spark ,所以我们下面就有一些例子,当然大家也可以自行去补充

统计每天的成交额

下面我们统计一下每天的成交额,这也是最简单的了

def lastDaysamount(): Unit ={
    sql(
      """
        |select
        |   trade_date,sum(amount) as amount
        |from
        |   trade
        |group by
        |   trade_date
        |order by
        |   trade_date desc
        |limit
        |   20
        |""".stripMargin
    ).show(20,false)

  }

统计结果

+----------+---------------------+
|trade_date|amount               |
+----------+---------------------+
|20211101  |1.2228828557399983E12|
|20211029  |1.1381616219410015E12|
|20211028  |1.1072842704220002E12|
|20211027  |1.0765778557610035E12|
|20211026  |1.0821421444879968E12|
|20211025  |1.0145576773829996E12|
|20211022  |1.0149981487659999E12|
|20211021  |9.92753188046003E11  |
|20211020  |1.0197585589460028E12|
|20211019  |9.730877555890015E11 |
|20211018  |1.0019797845380023E12|
|20211015  |9.888019904729999E11 |
|20211014  |8.606463289579985E11 |
|20211013  |8.894112029519983E11 |
|20211012  |9.962537488750033E11 |
|20211011  |9.918985312839995E11 |
|20211008  |1.0603440896720006E12|
|20210930  |9.502251816350017E11 |
|20210929  |1.0775000013559976E12|
|20210928  |1.043524548934001E12 |
+----------+---------------------+

过去n天连续涨停的票

这个分析是这样的,用户输入一个数字n则代表的是过去n天,我们要做的的是筛选出过去连涨停n天、连涨停n-1天、连涨停n-2天一直到n-(n-1)天连续涨停的票,其实这个实现起来还是有一定难度的,因为这里有个累积的效果,而且就是连续涨停n天的票一定是涨停n-1天的,但是我们需要将它算在n 天里而不是n-1天。

def main(args: Array[String]): Unit = {
  // 股票交易数据
   val data=spark
     .read
     .option("header", true)
     .csv(path)
     .select("ts_code","trade_date","open","high","low","close","pre_close","change","pct_chg","vol","amount")

   // close 收盘价   pre_close 昨收价  change 涨跌额  pct_chg 	涨跌幅   vol 成交量 (手)  amount	 成交额 (千元)
   data.createOrReplaceTempView("trade")
   
  // 股票基本数据
   val stocks=spark
     .read
     .option("header", true)
     .csv(stocksPath)
   stocks.createOrReplaceTempView("stocks")
  
   // 连续涨停的方法 
   lastContinueDays(5)

}

因为直接使用SQL很难实现,所以我们这里使用了混合编程的方式,也就是借助scala 的for 循环和SQL 来配合实现

/**
 *
 * @param n 连续多少天
 */
def lastContinueDays(n:Int): Unit ={
  // 因为我们的n 是指n个交易日的数据,这里为了方便所以我们直接多取了一段时间的数据,直接来了个2倍,好的做法是你取dates 里面查
  val startDate = LocalDate.now().plusDays(-2*n).format(DateTimeFormatter.ofPattern("yyyyMMdd"))
  
  // 创建了一个空的实图,后面需要把for 循环里面的数据放到这个试图里面
  sql(
    """
      |select
      |   0 as days,null as ts_code,null as name,null as industry,null as market
      |""".stripMargin
  ).createOrReplaceTempView("base")
  
  // 循环实现上面的效果
  for(i <- 1 to n){
    sql(
      s"""
        |select
        |  ts_code,trade_date,open,high,low,close,pre_close,change,pct_chg,vol,amount,rn
        |from(
        |   select
        |      ts_code,trade_date,open,high,low,close,pre_close,change,pct_chg,vol,amount,row_number() over(partition by ts_code order by trade_date desc) as rn
        |   from
        |      trade
        |   where
        |     -- 时间要换掉 大致的过滤条件
        |     trade_date>='${startDate}'
        |)tmp
        |where
        |   -- 过去多少天
        |   rn<=$i
        |""".stripMargin
    ).createOrReplaceTempView("continuedays")
    // 更新数据到试图里
    sql(
      s"""
        |select
        |   $i as days,a.ts_code,b.name,b.industry,b.market
        |from(
        |   select
        |      ts_code
        |   from(
        |     select
        				-- pct_chg >=9.8涨停的定义
        |        ts_code,count(if(pct_chg>=9.8,ts_code,null)) as cnt
        |     from
        |        continuedays
        |     group by
        |        ts_code
        |   )tmp
        |   where
        |      cnt>=$i
        |) a
        |inner join
        |   stocks b
        |on
        |  a.ts_code=b.ts_code
        |union
         -- 获取到上一次for 循环的结果 
        |select
        |   days,ts_code,name,industry,market
        |from
        |   base
        |""".stripMargin
    ).createOrReplaceTempView("base")
    // 展示最后的结果
     sql(
      """
        |select
        |   days,ts_code,name,industry,market
        |from(
        |   select
        |      days,ts_code,name,industry,market,row_number()over(partition by ts_code order by days desc) as rn
        |   from
        |      base
        |)tmp
        |where
        |  rn=1
        |  and days!=0
        |order by
        |   days
        |""".stripMargin
    ).show(2000,false)
    
  }

我们看一下我们最终的效果,days 就是涨停的天数

+----+---------+-----------+--------+------+
|days|ts_code  |name       |industry|market|
+----+---------+-----------+--------+------+
|1   |603738.SH|泰晶科技   |元器件  |主板  |
|1   |301018.SZ|申菱环境   |专用机械|创业板|
|1   |300735.SZ|光弘科技   |通信设备|创业板|
|1   |300438.SZ|鹏辉能源   |电气设备|创业板|
|1   |603920.SH|世运电路   |元器件  |主板  |
|1   |002454.SZ|松芝股份   |汽车配件|中小板|
|1   |002463.SZ|沪电股份   |元器件  |中小板|
|1   |300594.SZ|朗进科技   |运输设备|创业板|
|1   |300365.SZ|恒华科技   |软件服务|创业板|
|1   |002483.SZ|润邦股份   |工程机械|中小板|
|1   |600295.SH|鄂尔多斯   |钢加工  |主板  |
|1   |603505.SH|金石资源   |矿物制品|主板  |
|1   |002610.SZ|爱康科技   |电气设备|中小板|
|1   |688059.SH|华锐精密   |机械基件|科创板|
|1   |603901.SH|永创智能   |专用机械|主板  |
|1   |603665.SH|康隆达     |纺织    |主板  |
|1   |600683.SH|京投发展   |区域地产|主板  |
|1   |688789.SH|宏华数科   |专用机械|科创板|
|1   |688518.SH|联赢激光   |专用机械|科创板|
|1   |603115.SH|海星股份   |元器件  |主板  |
|1   |603380.SH|易德龙     |元器件  |主板  |
|1   |300681.SZ|英搏尔     |汽车配件|创业板|
|1   |003043.SZ|华亚智能   |专用机械|中小板|
|1   |300835.SZ|龙磁科技   |元器件  |创业板|
|1   |600330.SH|天通股份   |元器件  |主板  |
|1   |605338.SH|巴比食品   |食品    |主板  |
|1   |688683.SH|莱尔科技   |化工原料|科创板|
|1   |300170.SZ|汉得信息   |软件服务|创业板|
|1   |001288.SZ|运机集团   |专用机械|主板  |
|1   |002522.SZ|浙江众成   |塑料    |中小板|
|1   |300990.SZ|同飞股份   |专用机械|创业板|
|1   |300953.SZ|震裕科技   |机械基件|创业板|
|1   |002701.SZ|奥瑞金     |广告包装|中小板|
|1   |603105.SH|芯能科技   |电气设备|主板  |
|1   |000931.SZ|中关村     |生物制药|主板  |
|1   |002571.SZ|德力股份   |玻璃    |中小板|
|1   |300617.SZ|安靠智电   |电气设备|创业板|
|1   |002916.SZ|深南电路   |元器件  |中小板|
|1   |603948.SH|建业股份   |化工原料|主板  |
|1   |300260.SZ|新莱应材   |机械基件|创业板|
|2   |688033.SH|天宜上佳   |运输设备|科创板|
|2   |603348.SH|文灿股份   |汽车配件|主板  |
|2   |300052.SZ|中青宝     |互联网  |创业板|
|2   |688008.SH|澜起科技   |半导体  |科创板|
|2   |603399.SH|吉翔股份   |小金属  |主板  |
|2   |002837.SZ|英维克     |专用机械|中小板|
|2   |603088.SH|宁波精达   |专用机械|主板  |
|2   |603063.SH|禾望电气   |电气设备|主板  |
|2   |603836.SH|海程邦达   |仓储物流|主板  |
|2   |002824.SZ|和胜股份   |铝      |中小板|
|2   |600742.SH|一汽富维   |汽车配件|主板  |
|2   |601218.SH|吉鑫科技   |机械基件|主板  |
|2   |605286.SH|同力日升   |运输设备|主板  |
|2   |600696.SH|岩石股份   |区域地产|主板  |
|3   |002805.SZ|丰元股份   |化工原料|中小板|
|3   |002815.SZ|崇达技术   |元器件  |中小板|
|3   |600556.SH|天下秀     |互联网  |主板  |
+----+---------+-----------+--------+------+

统计分析打板策略

这个我们就不演示了,我们只分析一件事情,就是如何打板才能最大概率赚到钱,就是我们可以分析过去一天涨停今天还涨的股票,分析过去两天涨停今天涨的概率,一直到过去10天涨停今天涨的概率,其实很多人都喜欢打板,但是可能大家都没分析过大板的胜率

总结

今天我们通过使用 Spark SQL来分析股票数据,但是分析的目的不是为了买股票,而是为了学习和掌握Spark SQL