整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

编写一个获得股票信息的程序,供以后自己程序分析用

位老总,有时我们想钱想疯了(没办法,上有老,下有小),就去玩股票,虽然大多数当菲菜,让人割了,但还是乐此不疲。

上APP、上软件看各股资料太麻烦?不好找出各股的对比数据?那你可以把各股资料放入数据库,像平常我们玩数据库一样,想查哪个市值多少,哪个地方的,非常方便。

下面程序是我之前写的读取各股票信息,然后存到数据库里,供自己分析,大家可以参考,编写更详细的信息。

主要是读取东方财富网的数据

上证各股资料的URL都是:http://quote.eastmoney.com/sh+股票编号.html

深上证各股资料的URL都是:http://quote.eastmoney.com/sz+股票编号.html

代码如下(几年前的JAVA代码,能运行就得了)

package yjz.nms.cla;

import java.io.BufferedReader;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.UnsupportedEncodingException;

import java.net.ConnectException;

import java.net.MalformedURLException;

import java.net.URL;

import java.net.URLConnection;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.util.regex.Matcher;

import java.util.regex.Pattern;

public class GetStockInfo {

public void getData() throws IOException {

//股票名

String stockname=null ;

//板块

String bankuai=null;

//业务范围

String yewufanwei=null ;

//概念

String gainian=null ;

//发行价

float faxingjia;

//注册资本

float zhuceziben = 0 ;

//市值

float shizhi ;

//市盈率

float shiyinglv = 0 ;

//每股收益

float meigushouyi = 0 ;

//业务收入

float yingyeshouru = 0 ;

//收入同比

float shourutongbi ;

//利润

float liren = 0 ;

//利润同比

float lirentongbi ;

//市净率

float shijinglv ;

Connection con = null;

// 连接数据库

con = connDB(con);

String codeSqe=null;

codeSqe=getCodeSeq(con );

String fileNameN = "e:\allStockCode.ini";

File f = new File(fileNameN);

String data = null;

if (f.exists()) {

BufferedReader br = new BufferedReader(new InputStreamReader(

new FileInputStream(fileNameN), "UTF-8"));

while((data=br.readLine())!=null && ! data.equals("")){

data=data.substring(data.indexOf("(")+1,data.indexOf(")"));

String urls = null;

if (data.startsWith("60")) {

urls = "http://quote.eastmoney.com/sh"+data+".html";

} else {

urls = "http://quote.eastmoney.com/sz"+data+".html";

}

String htmlContent= getHtmlContent(urls,"gb2312");

stockname = getContent(htmlContent,"<h2 class=\"header-title-h2 fl\" id=\"name\">(.*?)</h2>");

shizhi = Float.parseFloat(getContent(htmlContent,"<span id=\"gt7_2\">(.*?)亿</span>"));

String tmp=getContent(htmlContent,"<span id=\"gt6_2\">(.*?)</span>");

if(tmp.indexOf("-")<0){

shiyinglv = Float.parseFloat(tmp);

}

tmp=getContent(htmlContent,"收益</a>.*(\d+\.\d+?)</td>");

if(tmp.indexOf("-")<0){

meigushouyi = Float.parseFloat(tmp);

}

String yingyeshourus = getContent(htmlContent,"<td>收入:(.*?)</td>");

if(yingyeshourus.indexOf("亿")>0){

yingyeshouru=Float.parseFloat(yingyeshourus.substring(0,yingyeshourus.indexOf("亿")))*10000;

}else{

yingyeshouru=Float.parseFloat(yingyeshourus.substring(0,yingyeshourus.indexOf("万")));

}

shourutongbi = Float.parseFloat(getContent(htmlContent,"同比</a>:(.*?)%</td>"));

String lirens = getContent(htmlContent,"<td>净利润:(.*?)</td>");

if(lirens.indexOf("亿")>0){

liren=Float.parseFloat(lirens.substring(0,lirens.indexOf("亿")))*10000;

}else{

tmp=lirens.substring(0,lirens.indexOf("万"));

liren=Float.parseFloat(tmp);

}

lirentongbi = Float.parseFloat(getContent(htmlContent,"<td>同比:(.*?)%</td>"));

shijinglv = Float.parseFloat(getContent(htmlContent,"<td>市净率:<span id=\"gt13_2\">(.*?)</span></td>"));

if (data.startsWith("60")) {

urls = "http://f10.eastmoney.com/f10_v2/CompanySurvey.aspx?code=sh"+data;

} else {

urls = "http://f10.eastmoney.com/f10_v2/CompanySurvey.aspx?code=sz"+data;

}

htmlContent= getHtmlContent(urls,"utf-8");

yewufanwei = getContent(htmlContent,"<th class=\"tips-fieldnameL\">经营范围</th><td colspan=\"3\" class=\"tips-dataL tips-lineheight\" width=\"782\">(.*?)</td>");

bankuai = getContent(htmlContent,"<th class=\"tips-fieldnameL\">所属行业</th><td class=\"tips-dataL\">(.*?)</td></tr>");

String zhucezibens = getContent(htmlContent,"注册资本\(元\)</th><td class=\"tips-dataL\">(.*?)</td>");

if(zhucezibens.indexOf("亿")>0){

zhuceziben=Float.parseFloat(zhucezibens.substring(0,zhucezibens.indexOf("亿")))*10000;

}else{

zhuceziben=Float.parseFloat(zhucezibens.substring(0,zhucezibens.indexOf("万")));

}

System.out.println(getContent(htmlContent,"每股发行价\(元\)</th><td class=\"tips-dataL\">(.*?)</td>"));

faxingjia= Float.parseFloat(getContent(htmlContent,"每股发行价\(元\)</th><td class=\"tips-dataL\">(.*?)</td>"));

if (data.startsWith("60")) {

urls = "http://f10.eastmoney.com/f10_v2/CoreConception.aspx?code=sh"+data;

} else {

urls = "http://f10.eastmoney.com/f10_v2/CoreConception.aspx?code=sz"+data;

}

htmlContent= getHtmlContent(urls,"utf-8");

gainian= getContent(htmlContent,"<p>要点一:<font>所属板块</font> (.*?)</p>");

/*System.out.println("data:"+data);

System.out.println("stockname:"+stockname);

System.out.println("bankuai:"+bankuai);

System.out.println("yewufanwei:"+yewufanwei);

System.out.println("gainian:"+gainian);;

System.out.println("faxingjia:"+faxingjia);

System.out.println("zhuceziben:"+zhuceziben);

System.out.println("shizhi:"+shizhi);

System.out.println("shiyinglv:"+shiyinglv );

System.out.println("meigushouyi:"+meigushouyi );

System.out.println("yingyeshouru:"+yingyeshouru);

System.out.println("shourutongbi:"+shourutongbi);

System.out.println("liren:"+liren );

System.out.println("lirentongbi:"+lirentongbi);

System.out.println("shijinglv:"+shijinglv);*/

if((codeSqe==null) || (!codeSqe.contains(data))){

try {

String insertsql = "insert into stockINFO(stockcode , stockname, bankuai, yewufanwei,gainian ,faxingjia ,zhuceziben ,shizhi,shiyinglv ,meigushouyi,yingyeshouru ,shourutongbi,liren,lirentongbi,shijinglv)" +

" values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";

PreparedStatement pstmt = con.prepareStatement(insertsql);

pstmt.setString(1, data);

pstmt.setString(2, stockname);

pstmt.setString(3, bankuai);

pstmt.setString(4, yewufanwei);

pstmt.setString(5, gainian);

pstmt.setFloat(6, faxingjia);

pstmt.setFloat(7, zhuceziben);

pstmt.setFloat(8, shizhi);

pstmt.setFloat(9,shiyinglv);

pstmt.setFloat(10,meigushouyi );

pstmt.setFloat(11,yingyeshouru);

pstmt.setFloat(12,shourutongbi );

pstmt.setFloat(13,liren);

pstmt.setFloat(14,lirentongbi );

pstmt.setFloat(15,shijinglv );

int result = pstmt.executeUpdate();

if(result==1){

System.out.print("insert "+data+" into database ok");

}

pstmt.close();

} catch (SQLException e) {

System.out.println("SQL error"+data);

e.printStackTrace();

}catch (NumberFormatException e){

System.out.println("数安格式错"+data);

e.printStackTrace();

}

catch (StringIndexOutOfBoundsException e){

System.out.println("索引超出值"+data);

e.printStackTrace();

}

}else{

try {

String updatesql = "update stockINFO set stockname=?, bankuai=?, yewufanwei=?,gainian=? ,faxingjia=? ,zhuceziben=? ,shizhi=?,shiyinglv=? ,meigushouyi=?,yingyeshouru=? ,shourutongbi=?,liren=?,lirentongbi=?,shijinglv=? where stockcode=?" ;

PreparedStatement pstmt = con.prepareStatement(updatesql);

pstmt.setString(1, stockname);

pstmt.setString(2, bankuai);

pstmt.setString(3, yewufanwei);

pstmt.setString(4, gainian);

pstmt.setFloat(5, faxingjia);

pstmt.setFloat(6, zhuceziben);

pstmt.setFloat(7, shizhi);

pstmt.setFloat(8,shiyinglv);

pstmt.setFloat(9,meigushouyi );

pstmt.setFloat(10,yingyeshouru);

pstmt.setFloat(11,shourutongbi );

pstmt.setFloat(12,liren);

pstmt.setFloat(13,lirentongbi );

pstmt.setFloat(14,shijinglv );

pstmt.setString(15, data);

int result = pstmt.executeUpdate();

if(result==1){

System.out.print("update "+data+" into database ok");

}

pstmt.close();

} catch (SQLException e) {

System.out.println("SQL error"+data);

e.printStackTrace();

}catch (NumberFormatException e){

System.out.println("数安格式错"+data);

e.printStackTrace();

}

catch (StringIndexOutOfBoundsException e){

System.out.println("索引超出值"+data);

e.printStackTrace();

}

}

}

br.close();

br=null;

} else {

System.out.println("请在/slview/yjz,里面加上股票代码,用逗号分隔");

}

try {

con.close();

con=null;

} catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

private Connection connDB(Connection con) {

try {

Class.forName("oracle.jdbc.driver.OracleDriver");

} catch (Exception e) {

System.out.println("Can't load dbdriver!-->"

+ e.getMessage());

}

try {

con = DriverManager.getConnection(

"jdbc:oracle:thin:@127.0.0.1:1639:dbnms",

"abc", "dddd");

} catch (SQLException e1) {

// TODO Auto-generated catch block

e1.printStackTrace();

}

return con;

}

public String getCodeSeq(Connection con ){

PreparedStatement pstmt=null;

ResultSet rs=null;

StringBuffer bs=new StringBuffer();

String sql = "select distinct stockcode from stockINFO" ;

try {

pstmt = con.prepareStatement(sql);

rs=pstmt.executeQuery();

while(rs.next()){

bs.append(rs.getString(1)+",");

}

}catch (SQLException e) {

e.printStackTrace();

}

try {

rs.close();

rs=null;

pstmt.close();

pstmt=null;

} catch (SQLException e1) {

// TODO Auto-generated catch block

e1.printStackTrace();

}

return bs.toString();

}

public String getHtmlContent(String htmlURL,String code) {

URL url = null;

String rowContent = "";

StringBuffer htmlContent = new StringBuffer();

try {

url = new URL(htmlURL);

BufferedReader in = new BufferedReader(new InputStreamReader(url

.openStream(), code));

while ((rowContent = in.readLine()) != null) {

htmlContent.append(rowContent);

}

in.close();

} catch (MalformedURLException e) {

e.printStackTrace();

} catch (UnsupportedEncodingException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

return htmlContent.toString();

}

public String getContent(String htmlContent,String regex){

StringBuffer mainContent = new StringBuffer();

Pattern pattern = Pattern.compile(regex);

Matcher matcher = pattern.matcher(htmlContent);

if(matcher.find()) {

mainContent.append(matcher.group(1));

}

return mainContent.toString();

}

public static void main(String args[]) throws IOException,

InterruptedException {

GetStockInfo gsi=new GetStockInfo();

gsi.getData();

}

}

这个是只给大家一个参考,建议家里没有矿,还是少玩点。

者:Roman Orac
鱼羊 编译整理
量子位 报道 | 公众号 QbitAI

数据分析,如何能错过 Pandas

现在,数据科学家 Roman Orac 分享了他在工作中相见恨晚的 Pandas 使用技巧。

了解了这些技巧,能让你在学习、使用 Pandas 的时候更加高效。

话不多说,一起学习一下~

Pandas实用技巧

用 Pandas 做数据分析,最大的亮点当属 DataFrame。不过,在展示成果的时候,常常需要把 DataFrame 转成另一种格式。

Pandas 在这一点上其实十分友好,只需添加一行代码。

DataFrame 转 HTML

如果你需要用 HTML 发送自动报告,那么 to_html 函数了解一下。

比如,我们先设定这样一个 DataFrame:

import numpy as np
import pandas as pd
import random

n = 10
df = pd.DataFrame(
    {
        "col1": np.random.random_sample(n),
        "col2": np.random.random_sample(n),
        "col3": [[random.randint(0, 10) for _ in range(random.randint(3, 5))] for _ in range(n)],
    }
)

用上 to_html,就可以将表格转入 html 文件:

df_html = df.to_html()
with open(‘analysis.html’, ‘w’) as f: f.write(df_html)

与之配套的,是 read_html 函数,可以将 HTML 转回 DataFrame。

DataFrame 转 LaTeX

如果你还没用过 LaTeX 写论文,强烈建议尝试一下。

要把 DataFrame 值转成 LaTeX 表格,也是一个函数就搞定了:

df.to_latex()

DataFrame 转 Markdown

如果你想把代码放到 GitHub 上,需要写个 README。

这时候,你可能需要把 DataFrame 转成 Markdown 格式。

Pandas 同样为你考虑到了这一点:

print(df.to_markdown())

注:这里还需要 tabulate 库

DataFrame 转 Excel

说到这里,给同学们提一个小问题:导师/老板/客户要你提供 Excel 格式的数据,你该怎么做?

当然是——

df.to_excel(‘analysis.xlsx’)

需要注意的是,如果你没有安装过 xlwtopenpyxl 这两个工具包,需要先安装一下。

另外,跟 HTML 一样,这里也有一个配套函数:read_excel,用来将excel数据导入pandas DataFrame。

DataFrame 转字符串

转成字符串,当然也没问题:

df.to_string()

5个鲜为人知的Pandas技巧

此前,Roman Orac 还曾分享过 5 个他觉得十分好用,但大家可能没有那么熟悉的 Pandas 技巧。

1、data_range

从外部 API 或数据库获取数据时,需要多次指定时间范围。

Pandas 的 data_range 覆盖了这一需求。

import pandas as pd
date_from = “2019-01-01”
date_to = “2019-01-12”
date_range = pd.date_range(date_from, date_to, freq=”D”)
print(date_range)

freq = “D”/“M”/“Y”,该函数就会分别返回按天、月、年递增的日期。

2、合并数据

当你有一个名为left的DataFrame:

和名为right的DataFrame:

想通过关键字“key”把它们整合到一起:

实现的代码是:

df_merge = left.merge(right, on = ‘key’, how = ‘left’, indicator = True)

3、最近合并(Nearest merge)

在处理股票或者加密货币这样的财务数据时,价格会随着实际交易变化。

针对这样的数据,Pandas提供了一个好用的功能,merge_asof

该功能可以通过最近的key(比如时间戳)合并DataFrame。

举个例子,你有一个存储报价信息的DataFrame。

还有一个存储交易信息的DataFrame。

现在,你需要把两个DataFrame中对应的信息合并起来。

最新报价和交易之间可能有10毫秒的延迟,或者没有报价,在进行合并时,就可以用上 merge_asof。

pd.merge_asof(trades, quotes, on=”timestamp”, by=’ticker’, tolerance=pd.Timedelta(‘10ms’), direction=‘backward’)

4、创建Excel报告

在Pandas中,可以直接用DataFrame创建Excel报告。

import numpy as np
import pandas as pd

df = pd.DataFrame(np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]), columns=["a", "b", "c"])

report_name = 'example_report.xlsx'
sheet_name = 'Sheet1'
writer = pd.ExcelWriter(report_name, engine='xlsxwriter')
df.to_excel(writer, sheet_name=sheet_name, index=False)

不只是数据,还可以添加图表。

# define the workbook
workbook = writer.book
worksheet = writer.sheets[sheet_name]
# create a chart line object
chart = workbook.add_chart({'type': 'line'})
# configure the series of the chart from the spreadsheet
# using a list of values instead of category/value formulas:
#     [sheetname, first_row, first_col, last_row, last_col]
chart.add_series({
    'categories': [sheet_name, 1, 0, 3, 0],
    'values':     [sheet_name, 1, 1, 3, 1],
})
# configure the chart axes
chart.set_x_axis({'name': 'Index', 'position_axis': 'on_tick'})
chart.set_y_axis({'name': 'Value', 'major_gridlines': {'visible': False}})
# place the chart on the worksheet
worksheet.insert_chart('E2', chart)
# output the excel file
writer.save()

注:这里需要 XlsxWriter 库

5、节省磁盘空间

Pandas在保存数据集时,可以对其进行压缩,其后以压缩格式进行读取。

先搞一个 300MB 的 DataFrame,把它存成 csv。

df = pd.DataFrame(pd.np.random.randn(50000,300))
df.to_csv(‘random_data.csv’, index=False)

压缩一下试试:

df.to_csv(‘random_data.gz’, compression=’gzip’, index=False)

文件就变成了136MB。

gzip压缩文件可以直接读取:

df = pd.read_csv(‘random_data.gz’)

这一份Pandas技巧笔记,暂且说到这里。各位同学都做好笔记了吗?

Talk is cheap, show me the code。学会了,就用起来吧

— 完 —

量子位 QbitAI · 头条号签约

关注我们,第一时间获知前沿科技动态

文由ScriptEcho平台提供技术支持

项目地址:传送门

键盘精灵代码介绍

应用场景

键盘精灵是一款用于股票分析的辅助工具,通过键盘输入股票代码或拼音缩写,快速搜索并展示相关股票信息。它可以帮助交易者快速获取目标股票的实时行情、历史K线数据,并进行便捷的切换。

基本功能

  • **快速搜索股票:**通过键盘输入股票代码或拼音缩写,即可搜索并展示相关股票信息。
  • **展示股票信息:**搜索结果包括股票名称、代码、最新价格、涨跌幅等基本信息。
  • **切换股票:**选中搜索结果中的股票,即可切换当前显示的K线图和相关信息。
  • **发送股票代码到通达信:**通过键盘精灵,可以将股票代码直接发送到通达信软件,方便交易者快速下单或查看详细行情。

功能实现步骤及关键代码分析

1. 加载所需库和资源

let jsUrls = [
  // 加载JS库和资源
];
let styleUrls = [
  // 加载CSS样式
];

await Promise.all(styleUrls.map((styleUrl) => loadStyle(styleUrl)));
await Promise.all(jsUrls.map((jsUrl) => loadJavascript(jsUrl)));

2. 创建键盘精灵组件

function KeyboardChart(divDialog, divInput, div) {
  // 初始化键盘精灵组件
}

3. 创建K线图组件

function KLineChart(divKLine) {
  // 初始化K线图组件
}

4. 初始化组件并绑定事件

window.$(function () {
  // 创建K线图组件
  var klineControl = new KLineChart(document.getElementById('kline'));
  klineControl.Create();

  // 创建键盘精灵组件
  var divReport = document.getElementById('div_search_list');
  var divDialog = document.getElementById('div_keyboard');
  var divInput = document.getElementById('div_input_symbol');
  var reportCtrl = new KeyboardChart(divDialog, divInput, divReport);
  reportCtrl.Create();

// 绑定键盘精灵组件的股票切换回调函数
reportCtrl.ChangeSymbolCallback = function (sybmol) {
klineControl.ChangeSymbol(sybmol);
klineControl.Chart.SetFocus();
};
});

5. 键盘精灵组件功能实现

  • 搜索股票:
this.DivInput.addEventListener('keydown', (event) => {
  this.OnKeydown(event);
});
this.DivInput.addEventListener('keyup', (event) => {
  this.OnKeyup(event);
});
  • 切换股票:
this.Chart.AddEventCallback({
  event: JSCHART_EVENT_ID.ON_KEYBOARD_SELECTED,
  callback: (event, data, chart) => {
    this.OnSelectedSymbol(event, data, chart);
  },
});
  • 发送股票代码到通达信:
this.SendKeyToTDX = function (symbol) {
  // 发送股票代码到通达信
};

总结与展望

开发过程中的经验与收获:

  • 熟练掌握了使用JS和jQuery操作DOM元素和绑定事件。
  • 深入了解了股票分析软件中K线图和键盘精灵组件的实现原理。
  • 提升了对股票市场和金融数据的理解。

未来该卡片功能的拓展与优化:

  • **增强搜索功能:**支持拼音缩写、模糊搜索等方式。
  • **优化股票信息展示:**提供更全面的股票信息,如财务数据、行业分析等。
  • **集成更多功能:**如技术指标分析、量化交易策略等。
  • 更多组件:

获取更多Echos

本文由ScriptEcho平台提供技术支持

项目地址:传送门

微信搜索ScriptEcho了解更多