Rust学以致用(一)——读取k线csv文件,生成dataframe后计算MA5指标

一、业务内容

  • 读入csv文件到dataframe里
  • 生成新的列【“MA5"】
  • 计算MA5指标
  • 把dataframe重新保存成csv文件

二、涉及的rust知识

  • ploars包(用于dataframe的处理)的简单使用
  • dataframe增加列的操作
  • dataframe的打印
  • 自定义函数
  • 闭包的使用
  • 读取csv到df中
  • 把df保存到csv中
  • map的使用
  • series的切片
  • 条件表达式的使用

三、具体实现

1、待处理的csv文件——某只k线文件

在这里插入图片描述

2、包的引用

主要用到的是polars,这个包等同于python中的pandas以及julia中的dataframes。
参观和学习的地址:
官网地址:https://docs.rs/polars/latest/polars/
仓库地址:https://github.com/pola-rs/polars

extern crate polars; 
use polars::prelude::*;
use std::fs::File;

3、生成一个dataframe

DataFrame::default()

let mut df = DataFrame::default();

4、df里面增加一列

df.with_column()

df.with_column(Series::new("榜号",vec![1,2,3]));
df.with_column(Series::new("姓名",vec!["张三丰","黄老邪","老顽童"]));

5、 生成一个series

Series::new()

let mySeries = Series::new("姓名",vec!["张三丰","黄老邪","老顽童"]);

6、读取csv到df 中

CsvReader::new()

/// 功能:读取csv文件,转成dataframe
/// 输入:filePath:String ,文件路径和名字
/// 输出:Result<DataFrame> 
/// 
///  # Examples
/// ```
/// use polars::prelude::*;
/// use std::fs::File;
/// let df = read_csv("D:/csvTest/000004.csv".to_string());
/// println!("{:?}", df);
/// ```
/// 
fn read_csv(filePath: String) -> Result<DataFrame> 
{
    let file = File::open(filePath).expect("找不到文件");
    CsvReader::new(file)
        .infer_schema(None)
        .has_header(true)
        .finish()
}

测试代码:

use polars::prelude::*;
use std::fs::File;
let df = read_csv("D:/csvTest/000004.csv".to_string());
println!("{:?}", df);

7、把df保存成csv文件

write_csv::new()

/// 【功能】把dataframe保存成csv
/// 输入:
/// df: &mut DataFrame
/// filePath:String
/// 输出:Result<()>
/// 
///  # Examples
/// ```
/// extern crate polars; 
/// use polars::prelude::*;
/// let mut df = DataFrame::default();
/// df.with_column(Series::new("榜号",vec![1,2,3]));
/// df.with_column(Series::new("姓名",vec!["张三丰","黄老邪","老顽童"]));
/// write_csv(& mut df,"e:/bbb.csv".to_string());
/// ```
/// 
fn write_csv(df: &mut DataFrame,filePath:String) -> Result<()> {
    let mut file = File::create(filePath).expect("创建文件失败");

    CsvWriter::new(&mut file)
    .has_header(true)    //.has_headers(true)
    .with_delimiter(b',')
    .finish(df)
}

测试代码:

extern crate polars; 
use polars::prelude::*;
let mut df = DataFrame::default();
df.with_column(Series::new("榜号",vec![1,2,3]));
df.with_column(Series::new("姓名",vec!["张三丰","黄老邪","老顽童"]));
write_csv(& mut df,"e:/bbb.csv".to_string());

8、Series如何切片?

mySeries.slice()

let s = Series::new("x",  vec!(1,2,3,4,5,6));
let mySliceMean = s.slice(0,3).mean();  //从index为0的item开始取数据,取3个item
println!("{:?}",mySliceMean);

9、map的使用

  • 涵义
    map,apply以及C#中的select,他们其实是玩法相同。
    [1,2,3,4] × 2 = [2,4,6,8]
    对系列中的每个item都执行一次相同的处理,处理结果重新生成一个新的系列

  • 举例

(1)julia
f(x)=2x
[1,2,3,4] .|> f
结果
[2,4,6,8]

(2)C#
[1,2,3,4] .select(x=>2*x)
结果
[2,4,6,8]

(3)Rust

let q:Series = (0..100).map(|x|(2 * x) as i32).collect(); 
println!("{:?}", q);
[0,2,4,6,8,.......198]

夫人看了我写的代码,说了句:茴香豆的茴字都写出花来了,有意思吗?

10、闭包的使用

  • 话说什么是闭包?
    函数、匿名函数、委托、兰姆达、闭包,看见这些词,是不是有想吐的感觉——想吐就对了,我就经常吐。

对于大多数人而言,上古时代的编程语言多半是过程式,比如C.其它古早的函数式语言另论。

我们定义的变量一般都是用来存储数据的。加入有人提出:我有一个函数,我要把它存在一个变量里?
怎么弄,用一种特殊的变量,用来保存该函数的地址,这就是函数指针。

要调用一个函数,你的先定义一个有名有姓(函数签名)的函数,这是传统做法(明媒正娶,昭告乡间)。

后来有人说,我不想提前写那么多琐碎的小函数,我用的时候在定义,于是出现了现写现用的函数,在同一个代码块里面,写好一个临时的函数,然后接着就调用它,这个临时的函数就是匿名函数、表达式。(有点像童养媳了)。

后来有人说,我要在调用的时候直接写,于是你把函数逻辑直接写在一大条语句里,写完即代表调用结束,该求值的也求了,这就是闭包。(我也不知道怎么形容了)

  • rust中使用闭包

写在一行里面的闭包

let q:Series = (0..100).map(|x|(2 * x) as i32).collect(); 
println!("{:?}", q);

如果你的逻辑比较复杂,需要多行处理,那就写多行呗,如下所示,你还能写return!

 let q:Series = (0..100).map(
        |x|
        {
            let y = 2*x;
            
            return 2 * y;
        }
         as i32).collect();  //.collect::<i32<>>()
    println!("{:?}", q);

11、k线MA的计算函数

ma是啥,计算公式是啥,去查通*达&信软件,此地不敢多说,免得被封,直接上菜

///【功能】给定一个价格系列,计算周期为n的移动平均MA
fn Ma(prices:&Series,n:usize)->Vec<f32>
{
    (0..prices.len()).map(
        |x|-> f32
        {
            let m2 = if(x< n){
                NAN
            }
            else{
                prices.slice((x-n) as i64, n).mean().unwrap() as f32
            };

            return m2;           
        }
    ).collect::<Vec<f32>>() 
}

收尾:附上一个测试代码,没时间整理,随便看吧,我出门买菜去了


extern crate polars; 

//use polars::export::num::ToPrimitive;
// #[cfg(feature = "rolling_window")]
use polars::prelude::*;

use polars::df;
use std::f32::NAN;
use std::fs::File;

use std::collections::HashMap;

//use std::iter::zip;

fn main1() {
    println!("Hello, world!!!!!!");
    println!("who are you?");
    println!("Hello world");
    println!("Hello error2");
    format!("Hello {}", "world111111");

    let df = df!["字母" => ["a", "b", "c", "d"],"数字" => [1, 2, 3, 4]];
    println!("{:?}",df);
}

fn main2() 
{    
    let x = std::f64::consts::PI;
    let r = 8.0;
    println!("计算出来的面积为: {}", x * r * r);
}

/// 功能:读取csv文件,转成dataframe
/// 输入:filePath:String ,文件路径和名字
/// 输出:Result<DataFrame> 
/// 
///  # Examples
/// ```
/// use polars::prelude::*;
/// use std::fs::File;
/// let df = read_csv("D:/csvTest/000004.csv".to_string());
/// println!("{:?}", df);
/// ```
/// 
fn read_csv(filePath: String) -> Result<DataFrame> 
{
    let file = File::open(filePath).expect("找不到文件");

    CsvReader::new(file)
        .infer_schema(None)
        .has_header(true)
        .finish()
}

/// 【功能】把dataframe保存成csv
/// 输入:
/// df: &mut DataFrame
/// filePath:String
/// 输出:Result<()>
/// 
///  # Examples
/// ```
/// extern crate polars; 
/// use polars::prelude::*;
/// let mut df = DataFrame::default();
/// df.with_column(Series::new("榜号",vec![1,2,3]));
/// df.with_column(Series::new("姓名",vec!["张三丰","黄老邪","老顽童"]));
/// write_csv(& mut df,"e:/bbb.csv".to_string());
/// ```
/// 
fn write_csv(df: &mut DataFrame,filePath:String) -> Result<()> {
    let mut file = File::create(filePath).expect("创建文件失败");

    CsvWriter::new(&mut file)
    .has_header(true)    //.has_headers(true)
    .with_delimiter(b',')
    .finish(df)
}

fn read_csv_test()
{
    let df = read_csv("D:/csvTest/000004.csv".to_string());
    println!("{:?}", df);
}

fn main3()
{
    //main1();
    //main2();
    //read_csv_test()

    // use iterators
    let ca: UInt32Chunked = (0..10).map(Some).collect();
    println!("{:?}", ca);

    // from slices
    let ca = UInt32Chunked::new("foo", &[1, 2, 3]);
    println!("{:?}", ca);

    // use builders
    let mut builder = PrimitiveChunkedBuilder::<UInt32Type>::new("foo", 10);
    println!("-----------------------开始打印item------------------------");
    for value in 0..10 {
        println!("{}",value);
        builder.append_value(value);
    }
    println!("------------------------结束打印item-------------------------");
    let ca = builder.finish();
    println!("{:?}", ca);
}

fn main_dict()
{
    let mut hd: HashMap<&str,DataFrame> = HashMap::new();
    let df = read_csv("D:/csvTest/000004.csv".to_string()).unwrap();
    hd.insert(&"df", df); 
    println!("------------------------12131321321321321-------------------------");   
    println!("{:?}", hd["df"]);

    let k = &"df";
    hd.remove(k);
    println!("{}",hd.len());
}

fn main5()
{
    let mut df = read_csv("D:/csvTest/000004.csv".to_string()).unwrap();
    println!("{:?}", df);

    let ma5 = Series::new("ma5",&df["close"] + &df["open"]);    
    println!("{:?}", ma5);

    df.with_column(ma5); //df增加一列
    println!("{:?}", df);

    let x = df.column("open").unwrap();
    println!("{:?}",x);

    let y = &df["close"];
    println!("{:?}",y);    
    
    println!("{:?}",y); 
}

fn main6(){
    let arr = [100,200,300,400,500,600];  
    let mut i=0;  
    let a=&arr[1..=3];  
    let len=a.len();  
    println!("Elements of 'a' array:");  
    while i<len  
    {  
     println!("{}",a[i]);  
     i=i+1;  
    } 

    let mut df = read_csv("D:/csvTest/000004.csv".to_string()).unwrap();
    println!("{:?}", df);

    let x = df.column("open").unwrap();
    println!("{:?}",x);
}

///【功能】给定一个价格系列,计算周期为n的移动平均MA
fn Ma(prices:&Series,n:usize)->Vec<f32>
{
    (0..prices.len()).map(
        |x|-> f32
        {
            let m2 = if(x< n){
                NAN
            }
            else{
                prices.slice((x-n) as i64, n).mean().unwrap() as f32
            };

            return m2;           
        }
    ).collect::<Vec<f32>>() 
}

fn main(){
    let s = Series::new("x",  vec!(1,2,3,4,5,6));
    let mySliceMean = s.slice(0,3).mean();
    println!("{:?}",mySliceMean);

    let mut df = read_csv("D:/csvTest/000004.csv".to_string()).unwrap();
    println!("{:?}", df);

    let ma5 = Series::new("ma5",&df["close"]);    
    println!("{:?}", ma5);    

    let myMean = ma5.slice(0, 5).mean();
    println!("{:?}", ma5);

    let a = &df["close"];

    let v6 = Ma(&df["close"], 6);
    println!("{:?}", v6);
    let ma6= Series::new("ma6",v6);
    df.with_column(ma6); //df增加一列
    println!("{:?}", df);

    write_csv(& mut df,"e:/aaa.csv".to_string());

    let mut df = DataFrame::default();
    df.with_column(Series::new("榜号",vec![1,2,3]));
    df.with_column(Series::new("姓名",vec!["张三丰","黄老邪","老顽童"]));
    write_csv(& mut df,"e:/bbb.csv".to_string());

    let q:Series = (0..100).map(|x|(2 * x) as i32).collect();  //.collect::<i32<>>()
    println!("{:?}", q);

    let q:Series = (0..100).map(
        |x|
        {
            let y = 2*x;
            
            return 2 * y;
        }
         as i32).collect();  //.collect::<i32<>>()
    println!("{:?}", q);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值