Airthink


  • 首页

  • 分类

  • 归档

  • 标签

  • 关于

  • 搜索

面试题(查漏补缺)

发表于 2021-10-18 | 分类于 面基

List和Set的区别

List:有序集合,可重复,按对象的插入顺序保存。允许多个Null元素对象,可以使用iterator取出所有元素,在逐一遍历,还可以使用get(index)获取指定下标的元素。

Set:无序,不可重复。最多只允许有一个Null元素对象,取元素时只能用iterator接口取得所有元素,在逐一遍历。

ArrayList和LinkedList区别

ArrayList:基于动态数组实现,连续内存存储,适合下标访问(随机访问)。有扩容机制,因为数组长度固定,超出长度存数据时需要新建数组,然后将老数组拷贝到新的数组,如果不是尾部插入,还会涉及元素的移动。使用尾插法并指定初始容量可以极大提升性能。

LinkedList:基于链表实现,可以存储在分散的内存中,适合做数据的插入及删除操作,不适合查询。需要逐一遍历,遍历LinkedList必须使用iterator不能使用for循环,因为每次for循环体内通过get(i)取得某一元素时都需要对List重新遍历,性能消耗大。
另外不要用indexOf等返回元素索引,并利用其进行遍历,使用indexOf对list进行遍历,当结果未空时会遍历整个列表。

==和equals比较

==比较的是栈中的值,基本数据类型是变量值,引用类型是堆中内存对象的地址。
equals:object中默认也是采用==比较,但通常会重写。

接口和抽象类的区别

一个类只能继承一个抽象类,但可以实现多个接口。继承抽象类用关键字extends,实现接口用implements。

抽象类中的成员变量可以是各种类型的,而接口中的成员变量默认是public static final类型,必须赋初始值,不能被修改。

抽象类可以存在普通成员函数,接口只有定义,在JDK8之前方法被指定为public abstract,JDK8之后允许添加非抽象的方法,但是必须用default关键字修饰;定义了default的方法可以不被实现子类所实现,但可以被实现子类的对象调用。

接口的设计目的是对类的行为进行约束,也就是提供一种机制,可以强制要求不同类具有相同的行为,它只约束了行为的有无,但不对如何实现行为进行限制。

而抽象类的设计目的,是为了代码复用,当不同的类具有某些相同的行为,且其中一部分行为的实现方式一致(A的非真子集,记为B),可以让这些类都派生与一个抽象类。这个抽象类中实现了B,避免让所有的子类来实现B,这样就达到了代码复用的目的。而A-B的部分,留给各个子类自己实现。正是因为A-B在这里没有实现,所有抽象类不允许实例化。

抽象类是对类本质的抽象,表达的是is a的关系。抽象类包含并实现子类的通用特性,将子类存在差异化的特性进行抽象,交由子类去实现。

接口的核心是定义行为,,即实现类可以做什么,至于实现类主体是谁,如何实现,接口并不关心。

重载和重写的区别

重载:发生在同一个类中,方法名必须相同,参数类型不同,个数不同,顺序不同,方法返回值和访问修饰符可以不同。

重写:发生在父子类中,方法名,参数列表必须相同,返回值范围小于等于父类,抛出的异常范围小于等于父类,访问修饰符的范围大于等于父类,如果父类方法访问修饰符为private则子类就不能重写该方法。

HashMap相关

发表于 2021-10-18 | 分类于 面基

HashMap底层数据结构详解

JDK1.7及之前:数组+链表

JDK1.8:数组+链表+红黑树

HashMap添加元素时,会根据哈希值和数组长度来计算该元素put的位置。put元素会判断当前位置是否已经有元素,这样在多线程环境下,会发生数据覆盖,导致数据丢失。通常为了使元素分布均匀会使用取模运算,计算出index后,就会将改元素添加进去,但是会出现两个key的哈希值相同,这时候会产生哈希冲突,当哈希冲突时会产生链表的数据结构,冲突的元素会在该索引出以链表的形式保存。

但是当链表的长度过长时,其固有弊端就显示出来了,即查询效率低。

此时就引入了第三种数据结构,红黑树,红黑树是一刻接近于平衡的二叉树,远远比链表的查询料率高。但是如果链表的长度不到一定阈值,直接使用红黑树也不行,因为红黑树的自身维护代价也比较高,每插入一个元素都可能打破红黑树的平衡,这时候就需要对红黑树再平衡(左旋,右旋,重新着色)。

HashMap中数组的初始长度是16,默认的加载因子是0.75

数组一单达到容量的阈值就需要对数组进行扩容。扩容就意味着要进行数组的移动,数组一旦移动,每移动一次就要重新计算索引,这个过程牵扯大量元素的迁移,会大大影响效率。如果直接使用与运算,这个效率远远高于取模运算。

为什么链表长度大于等于8时转成了红黑树

遵循概率论里的泊松分布。链表中元素个数为8的概率已经非常小,红黑树平均查找长度是log(n),当长度为8时,平均查找长度为3,如果继续使用链表,平均查找长度为8、2=4,这时候才有转为树的必要。

HashMap的遍历方式

迭代器遍历(iterator)

For Each方式遍历

Lambda表达式遍历

Streams Api遍历

迭代器entrySet

@Test
public void test001(){
    Map<String, Integer> map = new HashMap<>();
    map.put("1",1);
    map.put("2",2);
    Iterator<Map.Entry<String,Integer>> iterator = map.entrySet().iterator();
    while (iterator.hasNext()){
        Map.Entry<String,Integer> entry = iterator.next();
        System.out.println("key:"+entry.getKey()+",value:"+entry.getValue());
    }
}

当遍历时涉及到删除操作,建议使用iterator的remove方法。使用forEach会报错。

迭代器keySet

@Test
public void test002(){
    Map<String, Integer> map = new HashMap<>();
    map.put("11",1);
    map.put("22",2);
    Iterator<String> iterator = map.keySet().iterator();
    while (iterator.hasNext()){
        String key = iterator.next();
        System.out.println("key:"+key+",value:"+map.get(key));
    }
}

ForEach EntrySet

@Test
public void test003(){
    Map<String, Integer> map = new HashMap<>();
    map.put("111",1);
    map.put("222",2);
    for (Map.Entry<String,Integer> entry:map.entrySet()
         ) {
        System.out.println("key:"+entry.getKey()+",value:"+entry.getValue());
    }
}

通过Map.entrySet遍历key和value,代码简洁高效,推荐使用

ForEach keySet(如果只需要获取所有的key,推荐使用,比entrySet遍历要快,代码简洁)

@Test
public void test004(){
    Map<String,Integer> map = new HashMap<>();
    map.put("1111",1);
    map.put("2222",2);
    for (String str:
         map.keySet()) {
        System.out.println("key:"+str+",value:"+map.get(str));
    }
}

根据键取值是耗时操作,不推荐使用


如果只需要获取所有的value,推荐使用,比entrySet快,简洁

@Test
public void test004(){
    Map<String,Integer> map = new HashMap<>();
    map.put("1111",1);
    map.put("2222",2);
    for (String str:
         map.values()) {
        System.out.println("value:"+str);
    }
}

Lambda表达式

@Test
public void test005(){
    Map<String,Integer> map = new HashMap<>();
    map.put("11111",1);
    map.put("22222",2);
    map.forEach((key,value)->{
        System.out.println("key:"+key+",value:"+value);
    });
}

Streams API单线程

 @Test
public void test006(){
    Map<String,Integer> map = new HashMap<>();
    map.put("111111",1);
    map.put("222222",2);
    map.entrySet().stream().forEach((entry)->{
        System.out.println("key:"+entry.getKey()+",value:"+entry.getValue());
    });
}

Streams API多线程

@Test
public void test007(){
    Map<String,Integer> map = new HashMap<>();
    map.put("1111111",1);
    map.put("2222222",2);
    map.entrySet().parallelStream().forEach((entry)->{
        System.out.println("key:"+entry.getKey()+",value:"+entry.getValue());
    });
}

TBQUANT

发表于 2021-05-22 | 分类于 投资

输出

PlotString("BarStatus",Text(BarStatus));

定义参数

整个公式中只能出现一个 Params 宣告,并且要放到公式的开始部分,在变量定义之前

Params
 Bool bTest(False); //定义布尔型参数 bTest,默认值为 False;
 Numberic Length(10); //定义数值型参数 Length,默认值为 10;
 NumericSeries Price(0); //定义数值型序列参数 Price,默认值为 0;
 NumericRef output(0); //定义数值型引用参数 output,默认值为 0;
 String strTmp("Hello"); //定义字符串参数 strTmp,默认值为 Hello

定义变量

整个公式中只能出现一个 Vars 声明,并且要放到公式的开始部分,在参数定义之后,正文之前。

Vars
NumericSeries MyVal1(0); //定义数值型序列变量 MyVal1,默认值为 0;
Numeric MyVal2(0); //定义数值型变量 MyVal2,默认值为 0;
Bool MyVal3(False); //定义布尔型变量 MyVal3,默认值为 False;
String MyVal4("Test"); //定义字符串变量 MyVal4,默认值为 Test。

用户函数编写示例

Average 函数脚本如下:
Params
NumericSeries Price(1);
Numeric Length(10);
Vars
Numeric AvgValue; 
Begin
AvgValue = Summation(Price, Length) / Length;
Return AvgValue;
End

上面的例子,返回值只有一个,即最后求得的平均值,在函数中直接使用 Return 语句返回就可以
了。

Params
NumericSeries Price(1);
Numeric Length(10);
NumericRef HighestBar; //设置引用型的变量
Vars
Numeric MyVal;TradeBlazer 公式开发指南 TradeBlazer 用户函数
- 69 -
Numeric MyBar;
Numeric i; 
Begin
MyVal = Price;
MyBar = 0;
For i = 1 to Length – 1
{
If ( Price[i] > MyVal)
{
MyVal = Price[i];
MyBar = i; //记录最大值 Bar 与当前 Bar 的偏移量
}
}
HighestBar = MyBar; //通过将偏移量赋值给引用型变量,它可将该值传递回去
Return MyVal;
End

函数参数声明类型 可传入的变量类型
Numeric== Numeric,NumericRef,NumericSeries
NumericRe==f Numeric,NumericRef
NumericSeries== Numeric,NumericRef,NumericSeries
Bool== Bool,BoolRef,BoolSeriesTradeBlazer
BoolRef== Bool,BoolRef
BoolSeries== Bool,BoolRef,BoolSeries
String== String,StringRef,StringSeries
StringRef== String,StringRef
StringSeries== String,StringRef,StringSeries 

输出

PlotNumeric-----在当前 Bar 输出一个数值;
语法:PlotNumeric(String Name,Numeric Number,Numeric Locator=0,Integer Color=-1,Integer 
BarsBack=0)
 Name 输出值的名称的字符串,可以为中、英文、数字或者其它字符;
 Number 输出的数值;
 Locator 输出值的定位点,默认时输出单点,否则输出连接两个值线段,用法请看例 2;
 Color 输出值的显示颜色,默认表示使用属性设置框中的颜色;
 BarsBack 从当前 Bar 向前回溯的 Bar 数,默认值为当前 Bar。
例 1:PlotNumeric ("RSI",RSIValue);
输出 RSI 的值。
例 2:PlotNumeric ("OpenToClose",Open,Close);
输出开盘价与收盘价的连线。(需要在公式属性的输出线形选择柱状图)
例 3:PlotNumeric ("AvgValue",average(close,5),0,Blue);
输出一条蓝色的以收盘价计算的五日平均线。
注意:当后面的参数都使用默认值的情况下,可省略不写,如例 1。但如果后面还有其它参数要指明,
而只是中间某一个或者多个参数需要默认值的话,则中间参数不可省略,需将默认值一一填写,如例


PlotBool-----在当前 Bar 输出一个布尔值。
语法:PlotBool(String Name,Bool bPlot,Numeric Locator=0,Integer Color=-1,Integer BarsBack=0)
Name 输出值的名称,不区分大小写;
bPlot 输出的布尔值;
Locator 输出值的定位点;
Color 输出值的显示颜色,默认表示使用属性设置框中的颜色
BarsBack 从当前 Bar 向前回溯的 Bar 数,默认值为当前 Bar 

示例 :PlotBool ("con",con,High); 
在 Bar 的最高价位置输出条件 con 的布尔值。
PlotString-----在当前 Bar 输出一个字符串。
语法:PlotString(String Name,String str,Numeric Locator=0,Integer Color=-1,Integer BarsBack=0)
Name 输出值的名称,不区分大小写;
str 输出的字符串;
Locator 输出值的定位点;
Color 输出值的显示颜色,默认表示使用属性设置框中的颜色;
BarsBack 从当前 Bar 向前回溯的 Bar 数,默认值为当前 Bar。
示例 :
PlotString ("Bear Market","Bear Bear",High,Blue); 
在 Bar 的最高价位置输出一个蓝色的字符串 Bear Bear

公式正文

参数与变量的声明之后,在公式的正文部分,对所声明的变量进行赋值计算,必要的话还可以将所需的
条件语句编写进公式里。最后则是将计算结果以数值、布尔或字符串的形式在图表上输出。
现在我们来试着建立一个技术分析类的公式应用。首先,需要确立我们的指标里需要什么信息,以及需
要通过何种计算从而得到我们想要的结果。比如,现在我们需要得到两条移动平均线,那么首先可以确
定,要输出的是两个数值型的变量的值,然后我们就可以在公式中进行定义与赋值了。
有如下代码:

Params //参数的声明
numeric length1(10);
numeric length2(20);
Vars //变量的声明
numeric ma1;
numeric ma2;
Begin
ma1 = averageFC(close,length1);
ma2 = averageFC(close,length2); // 给变量的赋值
PlotNumeric("ma1",ma1,0,cyan);
PlotNumeric("ma2",ma2,0,Magenta); //输出计算出来的平均值
End

以上公式先声明参数与变量,然后在 Begin 与 End 之间对公式的主体进行了赋值与输出。

交易指令函数

交易开拓者提供 Buy,SellShort, BuyToCover,Sell,A_SendOrder 这五个函数来做下单的动作
指令。

Buy,SellShort, BuyToCover,Sell 这四个函数可以针对历史数据在图表上做出讯号标识,同时在实
时行情中也可以及时地发出下单委托的动作。因为可以对历史数据的图表上做出讯号的标识记录,交易
设置的性能测试也需要由这几个函数参与计算的公式应用方可实现。

Buy —- 对当前合约发出买入开仓的指令,如果图表讯号显示当前持有空仓,则会先平掉空仓,再开多
仓;

SellShort —- 对当前合约发出卖出开仓的指令,如果图表讯号显示当前持有多仓,则会先平掉多仓,再
开空仓;

BuyToCover —- 对当前合约发出平空仓的指令,当图表讯号显示有空头持仓时,方可执行此指令;

Sell —- 对当前合约发出平多仓的指令,当图表讯号显示有多头持仓时,方可执行此指令;

if(condition1 && marketposition!=1) //条件满足且没有持多仓情况下开多
{
 buy();
}else if(condition2 && marketposition!=-1) //条件满足且没有持空仓时开空
{
sellshort();
}

调试语句输出

If(close>open)
 Commentary("收阳="+Text(close)); // 在收阳的 K 线上显示收盘价

量化投资基础知识

发表于 2021-04-29 | 分类于 投资

夏普比率(SharpeRatio)

夏普比率可以理解为风险调整后的收益,衡量的是每承受一单位风险,会产生多少超额报酬。既然重点在回报上,当然是希望同样的风险,能获得更高的回报;或者说当回报相同时,风险更小。

敲黑板:夏普比率越大越好

最大回撤率(DrawDown)

在选定周期内任一时点往后推,基金净值在最低点时的收益下跌幅度的最大值。最大回撤代表投资者可能面临的最大亏损。

敲黑板:最大回撤率越小越好

年度收益率(Annual Return)

考驾照

发表于 2021-02-28 | 分类于 驾照

系安全带,查看方向盘是否回正,挡位是否在空挡,手刹是否拉起

坡道定点停车和起步

一档上坡,要对好边缘线,与右侧边缘线保持30cm。

左后视镜可看到坡起实线踩离合踩刹车。

拉起手刹停留超过3秒钟,放下手刹。

缓抬离合至车身抖动保持不动,松掉刹车,完成起步。

侧方位停车

一档行车,车身离边缘线30cm-50cm为宜,当从右侧后视镜看到库位前角时候,踩离合踩刹车停车。

挂倒挡,松刹车慢松离合开始倒车,当库位前角从右侧后视镜消失时,向右打满方向盘,继续倒车。

观察左后视镜,当库位后角出现,回正方向盘继续倒车。

当左侧车门把手越过库位左侧虚线(左后车轮),向左打死方向盘继续倒车。

观察右后视镜,当车身与右侧边线平行踩离合踩刹车,完成入库。

挂一档,打左转向灯,松离合向前行驶,当车头中间将触及行车道左侧线向右回正方向盘继续行驶,完成出库。

直角转弯

一档行车,车身离右侧边缘线30cm为宜,进入项目打开左转向灯,当听到直角转弯关闭左转向灯。

观察左侧后视镜,当超过直角边五指向左打死方向盘,继续行驶。

观察右侧后视镜,车身与右侧边缘线平行回正方向盘,继续向前驶出项目。

曲线行驶

一档行车进入曲线行驶,当左侧大灯触及右侧曲线边缘线时,向左打一圈方向盘,保持左侧大灯沿着右侧边缘线行驶,直至第一个弯出来。

当左侧大灯触及左侧边缘线回正方向盘。

当右侧大灯触及左侧边缘线,当向右打一圈方向盘,保持右侧大灯贴左侧边缘线行驶,当驶出第二个弯,回正方向盘。

倒车入库

。。。

本杰明巴顿奇事

发表于 2021-02-12 | 分类于 电影台词
一直很好奇,街上是什么样子的?
下个街角又是怎么样?

Always had a healthy curiouly , what was up the street ? Or around the next corner ?

有时候,我感觉一切和前一天大不一样了。

Some days I feel different than the day before.

每个人在某种程度上都对自己有不同的认识,但是我们最后都会去往同一个地方,只是走的路不同罢了。

Everybody feels different about themselves , one way or another . Butwe’re all going the same way . Just taking different roads to get there ,that’s all . You’re on your own road .

有时候我觉得很可笑,那些在我们记忆里占据着很小一部分的人们,却往往给我们留下了最深刻的印象。
It’s funny how sometimes the people we remember the least , make the greatest impression on us .

我们注定要失去我们所爱的人,要不然我们怎么会知道,他们对我们有多么的重要。
We’re meant to lose the people we love . How else would we know how importantthey are to us ?

长大是件很有意思的事,不经意间就发生了,本来是这样一个人,然后突然间变成了另一个人,不再是原来那样子。

Growing up’s a funny thing , Sneak up on you . One person is there , than suddenly somebodyelse has taken here place . She wasn`t all albows and knees anymore.

你可以像疯狗那样对周围的一切愤愤不平,你可以诅咒命运,但是等到最后一刻,你还是得平静的放手而去。

You can be as mad as a mad dog at the way things went . You could swear, curse the fates . But when it comes to the end , you have to let go .

我们的生命因为各种各样的机遇而变得更有意义。

Our lives are defined by opportunities。

有些时候我们就活在即将发生冲撞的轨道上,浑然不知无论它是意外发生还是蓄谋已久,对此我们都无能为力。

Sometimes we’re on a collision course and we just don’t know it . Whether it’s by accident or by design , there’s not a thing we can do about it .

一件事无论太晚或者对于我来说太早,
都不会阻拦你成为你想成为的那个人,
这个过程没有时间的期限,只要你想,随时都可以开始,
要改变或者保留原状都无所谓,
做事本不应该有所束缚,
我们可以办好这件事却也可以把它搞砸,
但我希望最终你能成为你想成为的人。

For what it’s worth, it’s never too late,
Or in my case, too early,
To be whoever you want to be.
There’s no time limit, stop whenever you want.
You can change or stay the same.
There’s no rules to this thing.
We can make the best or the worst of it.
I hope you make the best of it.

我希望你有时能驻足于这个令你感到惊叹的世界,
体会你从未有过的感觉;
我希望你能见到其他与你观点不同的人们;
我希望你能有一个值得自豪的人生,
如果你想象的生活不一样;
我希望你能有勇气重新再来。

I hope you see things that startle you.
I hope you feel things you never felt before.
I hope you meet people with a different point of view.
I hope you live a life you’re proud of.
If you find that you are not,
I hope you have the strength to start all over again.

树莓派初始化设置

发表于 2021-02-10 | 分类于 linux

先执行
sudo apt-get install vim

WIFI设置
每当重新安装树莓派的系统或者初始化一块全新的树莓派都会遇到这样的问题:连接WIFI。

那当我们没有显示器和键盘的情况下怎末可以将树莓连接到当前的WIFI网络呢?

方法非常简单,首先在SD卡的根目录下添加一个名为 wpa_supplicant.conf的文件,然后在该文件内添加以下的内容:

country=CN
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
    ssid="AlexVB"
    key_mgmt=WPA-PSK
    psk="*********"
    priority=1
}

密码设置
树莓派很多功能都需要解锁root权限后才能完成,比如下载安装,更改文件等等。

在命令行界面执行以下命令,再输入两次想设置的root密码,执行后设置成功。

sudo passwd root

输入以下命令开启root权限:

sudo passwd --unlock root

更改pi用户密码:

sudo passwd pi

python设置
树莓派的python默认版本是python2.7,如果想用python3.x的话,树莓派有自带的python3.5,此乃大坑,不需要再下载python3,直接把python和自带的python3建立软链接就OK。

which python

/usr/bin/python

which python3

/usr/bin/python3

注意:不能直接就把python链接到python3上,会报错,先把原来的python2备份一下。
ln: 无法创建符号链接’/usr/bin/python’: 文件已存在

sudo mv /usr/bin/python  /usr/bin/python2

sudo ln -s /usr/bin/python3 /usr/bin/python

之后在终端输入python就可以看到python的默认版本改为python3.5了。
在这里插入图片描述

更改软件源
树莓派系统安装后默认使用国外的镜像源来更新软件,由于不可描述原因,国内访问速度非常慢,因此需要换成国内源。

树莓派官方提供了一个更新源列表,在这里我们使用中科大的软件源和系统源。

首先还是要备份原来的源文件:

sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak

sudo cp /etc/apt/sources.list.d/raspi.list /etc/apt/sources.list.d/raspi.list.bak

修改软件更新源,执行如下命令:

sudo vim /etc/apt/sources.list

将原来的内容注释掉,改为中科大的源:

deb http://mirrors.ustc.edu.cn/raspbian/raspbian/ stretch main contrib non-free rpi

在这里插入图片描述
修改系统更新源,执行如下命令:

sudo vim /etc/apt/sources.list.d/raspi.list

将原来的内容注释掉,改为中科大的源:

deb http://mirrors.ustc.edu.cn/archive.raspberrypi.org/debian/ stretch main ui

在这里插入图片描述
之后就可以快速更新和安装了。

sudo apt-get update

sudo apt-get upgrade -y

这时候可能会有提示“有些没有软件包是自动安装的但是当前已经不需要了,可以使用如下命令卸载:

sudo apt autoremove

!!千万别用!!
更改pip源
pip更换为国内源,可以大大的提高安装成功率和速度。

不管你用的是pip3还是pip,方法都是一样的,如下:

sudo vim /etc/pip.conf

更改文件内容:

index-url = https://mirrors.aliyun.com/pypi/simple

输入法

sudo apt-get install scim-pinyin

一、安装

1.安装mongodb

        sudo apt-get install mongodb

2. 启动服务

        /usr/bin/mongod -f /etc/mongodb.conf

3.启动命令行

        /usr/bin/mongo 

        此时可以看到版本是MongoDB shell version: 2.4.14

4.关闭mongo
      /usr/bin/mongod -shutdown -dbpath=/home/data/mongodb

二、配置

1.配置主机ip:

          sudo vim /etc/mongodb.conf

          加入如下:127.0.0.1,自己的ip

2.配置防火墙,让局域网环境可以访问数据库

          2.1  安装:sudo apt-get install ufw

          2.2  启用:sudo ufw enable

          2.3  禁止外部访问 sudo ufw default deny

          2.4  启用局域网mongodb端口访问:       sudo ufw allow from 192.168.0.0/8 

三、使用

1.pymongo下载

            这里注意,最新版本pymongo是不兼容MongoDB2.4的,所以下载的时候记得下载老版本

                  pip install pymongo==3.1.1

 2.使用

                  使用起来非常方便:连接、关闭、增删改查。具体操作见官网文档:

                  http://api.mongodb.com/python/current/index.html

python3.7导入gevent模块报错的解决方案

RuntimeWarning: greenlet.greenlet size changed, may indicate binary incompatibility. Expected 144, got 128
  return f(*args, **kwds)

pip3 install -U --force-reinstall --no-binary :all: gevent

安装64位

官方64位测试版系统下载地址

https://www.raspberrypi.org/forums/viewtopic.php?f=117&t=275370

换源

sudo vim /etc/apt/sources.list

deb https://mirrors.tuna.tsinghua.edu.cn/debian/ buster main contrib non-free
deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ buster main contrib non-free
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ buster-updates main contrib non-free
deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ buster-updates main contrib non-free
deb https://mirrors.tuna.tsinghua.edu.cn/debian/ buster-backports main contrib non-free
deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ buster-backports main contrib non-free
deb https://mirrors.tuna.tsinghua.edu.cn/debian-security buster/updates main contrib non-free
deb-src https://mirrors.tuna.tsinghua.edu.cn/debian-security buster/updates main contrib non-free


sudo vim /etc/apt/sources.list.d/raspi.list

deb http://mirrors.tuna.tsinghua.edu.cn/raspberrypi/ buster main ui

更新 sudo apt-get update

compose

发表于 2020-12-07 | 分类于 compose

如何写docker-compose.yml,Docker compose file 参考文档

Compose 简介

Compose 文件是一个YAML文件,用于定义services、netword和volumes。 Compose 文件的默认路径为./docker-compose.yaml(后缀为.yml和.yaml都可以)。

Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,您可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。

Compose 使用的三个步骤:

使用 Dockerfile 定义应用程序的环境。

使用 docker-compose.yml 定义构成应用程序的服务,这样它们可以在隔离环境中一起运行。

最后,执行 docker-compose up 命令来启动并运行整个应用程序。

安装 Docker Compose

sudo curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

docker-compose -v

工程、服务、容器

Docker Compose 将所管理的容器分为三层,分别是工程(project)、服务(service)、容器(container)

Docker Compose 运行目录下的所有文件(docker-compose.yml)组成一个工程,一个工程包含多个服务,每个服务中定义了容器运行的镜像、参数、依赖,一个服务可包括多个容器实例

Docker Compose默认的模板文件是docker-compose.yml,其中定义的每个服务都必须通过image指令指定镜像或使用Dockerfile的build指令进行自动构建,其它大部分指令跟docker run中选项类似。

如果使用Dockerfile的build指令,则在Dockerfile中设置的选项如CMD、EXPOSE、VOLUME、ENV等将会自动被获取,无需在docker-comopse.yml文件中再次设置。

如果使用image指定为镜像名称或镜像ID时镜像在本地不存在,Compose将会尝试去拉取这个镜像。

典型的docker-comopse.yml文件格式

version: '2'
services:
  web:
    image: dockercloud/hello-world
    ports:
      - 8080
    networks:
      - front-tier
      - back-tier

  redis:
    image: redis
    links:
      - web
    networks:
      - back-tier

  lb:
    image: dockercloud/haproxy
    ports:
      - 80:80
    links:
      - web
    networks:
      - front-tier
      - back-tier
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock 

networks:
  front-tier:
    driver: bridge
  back-tier:
driver: bridge

docker-compose.yml

version:指定 docker-compose.yml 文件的写法格式
services:多个容器集合
build:配置构建时,Compose 会利用它自动构建镜像,该值可以是一个路径,也可以是一个对象,用于指定 Dockerfile 参数

Compose文件是一个定义服务services、网络networks和卷volumes的YAML文件,默认路径是./docker-compose.yml,可使用.yml或.yaml作为文件扩展名。

服务services定义包含应用于为该服务启动的每个容器的配置,类似传递命令行参数一样docker container create。同样,网络networks和卷volumes的定义类似于docker network create和docker volume create。正如docker container create在Dockerfile指定选项,如CMD、EXPOSE、VOLUME、ENV,在默认情况下,不需要在docker-compose.yml配置中再次指定。可以使用Bash类${VARIABLE}语法在配置值中使用环境变量。

标准配置文件应该包含version、services、networks三部分,其中最关键的是services和networks两个部分。

images

images用来指定服务的镜像名称或镜像ID,如果镜像在本地不存在,compose将会尝试去拉取这个镜像。

services:
  web:
    image:redis

volumes

volumes指令用于设置数据卷挂载路径,数据卷挂载路径可以是一个目录或一个已经存在的数据卷容器,可以设置宿主机路径HOST:CONTAINER或加上访问模式HOST:CONTAINER:ro。使用ro表示对于容器来说数据卷是只读的,这样可以有效地保护宿主机的文件系统。

volumes:
  # 指定一个容器内的路径,Docker会自动创建一个数据卷。
  - /var/lib/mysql
  # 使用绝对路径挂载数据卷
  - /opt/data:/var/lib/mysql
  # 以compose配置文件所在目录为根的相对路径作为数据卷挂载到容器
  - ./cache:/tmp/cache
  # 使用用户的相对路径
  - ~/configs:/etc/configs:ro

networks

networks指令用于设置指定网络

services:
  some-service:
    networks:
      - some-network

多服务

version: '2'

services:

 service-eureka: 
   image: java
   volumes:
     - /Users/objcat/jar/service-eureka.jar:/usr/local/service-eureka.jar
   ports:
     - 8081:8081
   command:
     - /bin/sh
     - -c
     - |
       echo 192.168.1.126 servicehost >> /etc/hosts
       java -jar /usr/local/service-eureka.jar

 service-a: 
   image: java
   volumes:
     - /Users/objcat/jar/service-a.jar:/usr/local/service-a.jar
   ports:
     - 8082:8082
   command:
     - /bin/sh
     - -c
     - |
       echo 192.168.1.126 servicehost >> /etc/hosts
       java -jar /usr/local/service-a.jar

 service-b: 
   image: java
   volumes:
     - /Users/objcat/jar/service-b.jar:/usr/local/service-b.jar
   ports:
     - 8083:8083
   command:
     - /bin/sh
     - -c
     - |
       echo 192.168.1.126 servicehost >> /etc/hosts
       java -jar /usr/local/service-b.jar

arctic

发表于 2020-12-07 | 分类于 arctic

北极介绍

北极是位于MongoDB之上的时间序列/数据框架数据库。Arctic支持将许多数据类型序列号以存储在mongo文档模型中。

为什么使用北极

  • 序列化许多数据类型,例如Pandas DataFrames,Numpy数组,Python对象等,SO不必手动处理不同的数据类型。
  • 默认情况下客户端使用LZ4压缩,以节省大量网络/磁盘空间。
  • 允许对队形的不同阶段进行版本控制并快照状态(某种程度上类似于git),并允许自由的试验,然后紧还原快照。【仅限VersionStore】
  • 是否为您进行分块(将数据拆分为较小的部分)
  • 添加了可以在Mongo的auth上构建的Users and Per User Libraries的概念。
  • 拥有不同类型的商店,每种都有其自身的优势。Versionstore允许您对版本和快照内容进行版本控制,TickStore用于存储和高效检索流数据,ChunkStore允许您对数据块进行分块并有效地检索范围。
  • 限制对Mongo的数据访问,从而防止对未索引/未分片的集合进行临时查询

基本操作

Arctic提供了一个包装器,用于处理与Mongo的连接。该Arctic实际连接到北极。

conn = Arctic('127.0.0.1')

仅此连接句柄可以执行许多操作。最基本的是list_libraries和initiailize_library。

北极将数据分为不同的库。它们可能是不同的用户,不同的市场,不同的地理区域等。库名称是字符串,完全由用户定义。

conn.list_libraries()
[]

在这种情况下,系统上没有库,因此可以对其进行初始化。

>>> conn.initialize_library('library_name')
>>> conn.list_libraries()
[u'library_name']

initialize_library有一个名为arg的可选参数,lib_type默认为VersionStore(稍后会在Arctic存储引擎类型中提供更多信息)。

库初始化后,可以像这样访问它:

>>> lib = conn['library_name']

使用此库的句柄,我们可以开始从Arctic存储和检索数据。

(注意,大多数存储引擎的支持相同的基本方法(read,write,等),但每个人都有自己一套独特的方法为好)

write最基本的形式是北极symbol和数据。的symbol是,用于存储/检索数据的用户定义键。在data多数情况下是一个熊猫数据帧,虽然有些存储引擎支持其他类型的(所有支持dataframes,和一些支持类型的字典,并与pickle对象)。

read如您所料,会symbol读取数据。不同的存储引擎具有不同的参数,这些参数使您可以对数据进行子集设置(稍后会详细介绍)。

>>> data = pd.DataFrame(.....)
>>> lib.write('symbolname', data)
>>> df = lib.read('symbolname')
>>> df
                data
date
2016-01-01       1
2016-01-02       2
2016-01-03       3

其他基本方法:

  • library.list_symbols()
    符合您的期望-列出给定库中的所有符号 [‘US_EQUITIES’, ‘EUR_EQUITIES’, …]
  • arctic.get_quota(library_name), arctic.set_quota(library_name, quota_in_bytes)
  • 北极内部设置库的配额,这样它们就不会占用太多空间。您可以使用这两种方法检查和设置配额。请注意,这些操作针对 Arctic对象,而非库。

北极存储引擎

Arctic的设计具有很高的可扩展性,目前支持多种不同的用例。要了解Arctic的功能,必须了解其使用的存储模型。北极目前支持三个存储引擎

  • TickStore
  • 版本库
  • 块存储

每一个都有各种功能,旨在支持特定和通用的用例。

快速开始

安装北极

pip install git+https://github.com/manahl/arctic.git

运行一个mongo

mongod --dbpath <path/to/db_directory>

使用VersionStore

from arctic import Arctic
import quandl

# Connect to Local MONGODB
store = Arctic('localhost')

# Create the library - defaults to VersionStore
store.initialize_library('NASDAQ')

# Access the library
library = store['NASDAQ']

# Load some data - maybe from Quandl
aapl = quandl.get("WIKI/AAPL", authtoken="your token here")

# Store the data in the library
library.write('AAPL', aapl, metadata={'source': 'Quandl'})

# Reading the data
item = library.read('AAPL')
aapl = item.data
metadata = item.metadata

存储引擎版本库

VersionStore在MongoDB中序列化并存储Pandas对象,numpy数组以及其他python类型。修改versioneda时,对象是并且创建了新版本symbol。

使用VersionStore读写数据

from arctic import Arctic

a = Arctic(‘localhost’)
a.initialize_library('vstore')
lib = a[‘vstore’]

此时,您有一个空的VersionStore库。您不需要指定存储类型,因为VersionStore是Arctic中的默认库类型。您可以通过几种方式向其中写入数据。最基本的就是使用该write方法。写采用以下参数:

symbol, data, metadata=None, prune_previous_version=True, **kwargs

symbol是用于在北极存储/检索数据的名称。data是要存储在MongoDB中的数据。metadata是可选的用户定义元数据。它一定是一个dict。prune_previous_versions将删除/删除数据的先前版本(前提是快照中未包含它们)。kwargs被传递给各个写处理程序。有针对不同数据类型的写处理程序。

write用于写入和替换数据。如果test使用一个数据集写入符号,然后使用另一个数据集再次写入符号,则原始数据将被替换为新版本的数据。

>>> from pandas import DataFrame, MultiIndex
>>> from datetime import datetime as dt


>>> df = DataFrame(data={'data': [1, 2, 3]},
                   index=MultiIndex.from_tuples([(dt(2016, 1, 1), 1),
                                                 (dt(2016, 1, 2), 1),
                                                 (dt(2016, 1, 3), 1)],
                                                names=['date', 'id']))
>>> lib.write('test', df)
VersionedItem(symbol=test,library=arctic.vstore,data=<class 'NoneType'>,version=1,metadata=None,host=127.0.0.1)

>>> lib.read('test').data
               data
date       id      
2016-01-01 1      1
2016-01-02 1      2
2016-01-03 1      3


>>> df = DataFrame(data={'data': [100, 200, 300]},
                   index=MultiIndex.from_tuples([(dt(2016, 1, 1), 1),
                                                 (dt(2016, 1, 2), 1),
                                                 (dt(2016, 1, 3), 1)],
                                               names=['date', 'id']))

>>> lib.write('test', df)
VersionedItem(symbol=test,library=arctic.vstore,data=<class 'NoneType'>,version=2,metadata=None,host=127.0.0.1)

>>> lib.read('test').data
               data
date       id      
2016-01-01 1    100
2016-01-02 1    200
2016-01-03 1    300

write返回一个VersionedItem对象。VersionedItem包含以下成员:

符号
图书馆
版本-写入数据的版本号
元数据-元数据(如果存在),或无
数据(对于写入,它为None;对于读取,它包含从数据库读取的数据)。
主办
您还应注意,VersionStorewrite有效覆盖了已写入的数据。在上面的示例中,第二个示例用新数据帧write替换了符号test中的数据。原始数据(版本1)仍然可用,但必须以其版本号引用才能检索它。该read方法采用以下参数:

symbol, as_of=None, date_range=None, from_version=None, allow_secondary=None, **kwargs

as_of允许您检索特定时间点的数据。您可以通过多种方式定义该时间点。

  • 快照的名称(字符串)
  • 版本号(整数)
  • 日期时间(datetime.datetime)

date_range使您可以通过Arctic DateRange对象对数据进行子集化。DateRanges允许您指定日期范围(“ 2016-01-01”,“ 2016-09-30”),开始日期和结束日期以及开放式范围(无,“ 2016-09-30”)。范围可以在任一端打开。allow_secondary使您可以覆盖默认行为,以允许或禁止从mongo集群的辅助成员读取。

>>> lib.read('test').data
               data
date       id      
2016-01-01 1    100
2016-01-02 1    200
2016-01-03 1    300

>>> lib.read('test', as_of=1).data

date       id  data    
2016-01-01 1      1
2016-01-02 1      2
2016-01-03 1      3


>>> from arctic.date import DateRange
>>> lib.read('test', date_range=DateRange('2016-01-01', '2016-01-01')).data

date       id  data    
2016-01-01 1    100

DateRange仅适用于pandas DataFrame,并且该数据帧必须具有datetime索引。

写入数据的另一种方法是使用append方法。append接受以下参数:

symbol, data, metadata=None, prune_previous_version=True, upsert=True, **kwargs

upsert是唯一的新论据。upsert表示如果该符号不存在,它将创建它。如果upsert出现False错误,因为将没有现有数据要追加。

>>> lib.append('new', df, upsert=False)
~/arctic/arctic/store/version_store.py in append(self, symbol, data, metadata, prune_previous_version, upsert, **kwargs)
    505             return self.write(symbol=symbol, data=data, prune_previous_version=prune_previous_version, metadata=metadata)
    506 
--> 507         assert previous_version is not None
    508         dirty_append = False
    509 

AssertionError: 

lib.append(‘new’, df, upsert=True)
VersionedItem(symbol=new,library=arctic.vstore,data=,version=1,metadata=None,host=127.0.0.1)

实用方法

  • 删除
  • has_symbol
  • list_versions
  • read_metadata
  • write_metadata
  • restore_version

delete符合您的预期-从库中删除符号。它只有一个参数symbol。has_symbol并且list_symbols将返回有关库符号的当前状态信息。他们的签名是:

list_symbols(self, all_symbols=False, snapshot=None, regex=None, **kwargs)

def has_symbol(self, symbol, as_of=None)

for list_symbols,all_symbols如果设置为,则将true从所有快照返回所有符号,即使该符号已在当前版本中删除(但已保存在快照中)也是如此。snapshot允许您在指定的下方列出符号snapshot。regex允许您提供正则表达式以进一步限制查询返回的符号列表。北极使用MongoDB的$regex功能。Mongo支持PERL语法正则表达式;更多信息在这里

has_symbol返回True或False基于符号是否存在。您可以version通过将此检查限制为特定检查as_of。

>>> lib.delete('new')

>>> lib.list_symbols()
['test']

>>> lib.has_symbol('new')
False

>>> lib.write('test2', df)

>>> lib.list_symbols(regex=".*2")
['test2']

read_metadata并write_metadata允许您直接为给定符号读取/设置用户定义的元数据。

>>> lib.read_metadata('test2')
VersionedItem(symbol=test2,library=arctic.vstore,data=<class 'NoneType'>,version=1,metadata=None,host=127.0.0.1)

>>> lib.read_metadata('test2').metadata

>>> lib.write_metadata('test2', {'meta': 'data'})
VersionedItem(symbol=test2,library=arctic.vstore,data=<class 'NoneType'>,version=2,metadata={'meta': 'data'},host=127.0.0.1)

>>> lib.read_metadata('test2').metadata
{'meta': 'data'}

restore_version使您可以将最新版本设置为旧版本。您可以list_versions用来查看有关版本当前状态的信息。

>>> lib.list_versions('test') 
[{'symbol': 'test',
  'version': 3,
  'deleted': False,
  'date': datetime.datetime(2018, 8, 16, 17, 59, 47, tzinfo=tzfile('/usr/share/zoneinfo/America/New_York')),
  'snapshots': []},
 {'symbol': 'test',
  'version': 2,
  'deleted': False,
  'date': datetime.datetime(2018, 8, 15, 18, 0, 33, tzinfo=tzfile('/usr/share/zoneinfo/America/New_York')),
  'snapshots': []}]


>>> lib.restore_version('test', 2)
VersionedItem(symbol=test,library=arctic.vstore,data=<class 'NoneType'>,version=4,metadata=None,host=127.0.0.1)

>>> lib.read('test').data
               data
date       id      
2016-01-01 1    100
2016-01-02 1    200
2016-01-03 1    300

>>> lib.list_versions('test') 
[{'symbol': 'test',
  'version': 4,
  'deleted': False,
  'date': datetime.datetime(2018, 8, 16, 18, 54, 10, tzinfo=tzfile('/usr/share/zoneinfo/America/New_York')),
  'snapshots': []},
 {'symbol': 'test',
  'version': 3,
  'deleted': False,
  'date': datetime.datetime(2018, 8, 16, 17, 59, 47, tzinfo=tzfile('/usr/share/zoneinfo/America/New_York')),
  'snapshots': []},
 {'symbol': 'test',
  'version': 2,
  'deleted': False,
  'date': datetime.datetime(2018, 8, 15, 18, 0, 33, tzinfo=tzfile('/usr/share/zoneinfo/America/New_York')),
  'snapshots': []}]

使用restore_version不会删除最新版本,它只是使用用户提供的版本引用的数据创建了一个新版本。

快照

VersionStore允许您创建数据快照并为其分配名称。快照中仍包含属于快照的一部分的数据。快照方法是:

  • 快照
  • delete_snapshot
  • list_snapshots

snapshot允许您创建快照。它的签名很简单

snap_name, metadata=None, skip_symbols=None, versions=None

snap_name是要创建的快照的名称。metadata允许您向快照提供用户定义的元数据。skip_symbols允许您从快照中排除符号。versions允许您指定要包含在快照中的特定版本。

delete_snapshot和list_snapshot功能分别类似于delete和list_versions。list_snapshots返回snapshot映射到metadata快照的名称的字典。

>>> lib.list_symbols()
['test', 'test2']

>>> lib.snapshot('backup')

>>> lib.list_snapshots()
{'backup': None}

>>> lib.list_symbols(snapshot='backup')
['test', 'test2']

>>> lib.delete('test')

>>> lib.delete('test2')

>>> lib.list_symbols()
[]

>>> lib.list_symbols(snapshot='backup')
['test', 'test2']

>>> lib.read('test')
~/arctic/arctic/store/version_store.py in _read_metadata(self, symbol, as_of, read_preference)
    455         metadata = _version.get('metadata', None)
    456         if metadata is not None and metadata.get('deleted', False) is True:
--> 457             raise NoDataFoundException("No data found for %s in library %s" % (symbol, self._arctic_lib.get_name()))
    458 
    459         return _version

NoDataFoundException: No data found for test in library arctic.vstore


>>> lib.read('test', as_of='backup')
VersionedItem(symbol=test,library=arctic.vstore,data=<class 'pandas.core.frame.DataFrame'>,version=4,metadata=None,host=127.0.0.1)

>>> lib.read('test', as_of='backup').data 
               data
date       id      
2016-01-01 1    100
2016-01-02 1    200
2016-01-03 1    300

API参考

附加

append(symbol, item)
    Appends data from item to symbol's data in the database.

    Is not idempotent

    Parameters
    ----------
    symbol: str
        the symbol for the given item in the DB
    item: DataFrame or Series
        the data to append

用法示例:

>>> df = DataFrame(data={'data': [100, 200, 300]},
                  index=MultiIndex.from_tuples([(dt(2016, 1, 1), 1),
                                                (dt(2016, 1, 2), 1),
                                                (dt(2016, 1, 3), 1)],
                                               names=['date', 'id']))


>>> lib.write('test', df, chunk_size='M')
>>> lib.read('test')
               data
date       id
2016-01-01 1    100
2016-01-02 1    200
2016-01-03 1    300

>>> lib.append('test', df)
>>> lib.append('test', df)
>>> lib.read('test')
               data
date       id
2016-01-01 1    100
           1    100
           1    100
2016-01-02 1    200
           1    200
           1    200
2016-01-03 1    300
           1    300
           1    300

删除

delete(symbol, chunk_range=None)
    Delete all chunks for a symbol, or optionally, chunks within a range

    Parameters
    ----------
    symbol : str
        symbol name for the item
    chunk_range: range object
        a date range to delete

用法示例:

>>> lib.read('test')
               data
date       id
2016-01-01 1    100
2016-01-03 1    300

>>> lib.delete('test', chunk_range=pd.date_range('2016-01-01', '2016-01-01'))
>>> lib.read('test')
               data
date       id
2016-01-03 1    300

get_chunk_ranges

get_chunk_ranges(symbol, chunk_range=None, reverse=False)
    Returns a generator of (Start, End) tuples for each chunk in the symbol

    Parameters
    ----------
    symbol: str
        the symbol for the given item in the DB
    chunk_range: None, or a range object
        allows you to subset the chunks by range
    reverse: boolean

    Returns
    -------
    generator

用法示例:

>>> list(lib.get_chunk_ranges('new_name'))
[('2016-01-01', '2016-01-01'), ('2016-01-03', '2016-01-03')]

获取信息

get_info(symbol)
    Returns information about the symbol, in a dictionary

    Parameters
    ----------
    symbol: str
        the symbol for the given item in the DB

    Returns
    -------
    dictionary

迭代器

iterator(symbol, chunk_range=None):
    Returns a generator that accesses each chunk in ascending order

    Parameters
    ----------
    symbol: str
        the symbol for the given item in the DB
    chunk_range: None, or a range object
        allows you to subset the chunks by range

    Returns
    -------
    generator

list_symbols

list_symbols()
    Returns all symbols in the library

    Returns
    -------
    list of str

读

read(symbol, chunk_range=None, filter_data=True, **kwargs)
    Reads data for a given symbol from the database.

    Parameters
    ----------
    symbol: str
        the symbol to retrieve
    chunk_range: object
        corresponding range object for the specified chunker (for
        DateChunker it is a DateRange object or a DatetimeIndex,
        as returned by pandas.date_range
    filter_data: boolean
        perform chunk level filtering on the data (see filter in _chunker)
        only applicable when chunk_range is specified
    kwargs: ?
        values passed to the serializer. Varies by serializer

    Returns
    -------
    DataFrame or Series

用法示例:

>>> dr = pd.date_range(start='2010-01-01', periods=1000, freq='D')
>>> df = DataFrame(data={'data': np.random.randint(0, 100, size=1000),
                         'date': dr
                        })

>>> lib.write('symbol_name', df, chunk_size='M')
>>> lib.read('symbol_name', chunk_range=pd.date_range('2012-09-01', '2016-01-01'))
    data       date
0     61 2012-09-01
1     69 2012-09-02
2     96 2012-09-03
3     23 2012-09-04
4     66 2012-09-05
5     54 2012-09-06
6     21 2012-09-07
7     92 2012-09-08
8     95 2012-09-09
9     24 2012-09-10
10    87 2012-09-11
11    33 2012-09-12
12    59 2012-09-13
13    54 2012-09-14
14    48 2012-09-15
15    67 2012-09-16
16    73 2012-09-17
17    72 2012-09-18
18     6 2012-09-19
19    24 2012-09-20
20     8 2012-09-21
21    50 2012-09-22
22    40 2012-09-23
23    45 2012-09-24
24     8 2012-09-25
25    73 2012-09-26

改名

rename(from_symbol, to_symbol)
    Rename a symbol

    Parameters
    ----------
    from_symbol: str
        the existing symbol that will be renamed
    to_symbol: str
        the new symbol name

reverse_iterator

reverse_iterator(symbol, chunk_range=None):
    Returns a generator that accesses each chunk in descending order

    Parameters
    ----------
    symbol: str
        the symbol for the given item in the DB
    chunk_range: None, or a range object
        allows you to subset the chunks by range

    Returns
    -------
    generator

更新

update(symbol, item, chunk_range=None, upsert=False, **kwargs)
    Overwrites data in DB with data in item for the given symbol.

    Is idempotent

    Parameters
    ----------
    symbol: str
        the symbol for the given item in the DB
    item: DataFrame or Series
        the data to update
    chunk_range: None, or a range object
        If a range is specified, it will clear/delete the data within the
        range and overwrite it with the data in item. This allows the user
        to update with data that might only be a subset of the
        original data.
    upsert: bool
        if True, will write the data even if the symbol does not exist.
    kwargs:
        optional keyword args passed to write during an upsert. Includes:
        chunk_size
        chunker

写

write(symbol, item, chunker=DateChunker(), **kwargs)
    Writes data from item to symbol in the database

    Parameters
    ----------
    symbol: str
        the symbol that will be used to reference the written data
    item: Dataframe or Series
        the data to write the database
    chunker: Object of type Chunker
        A chunker that chunks the data in item
    kwargs:
        optional keyword args that are passed to the chunker. Includes:
        chunk_size:
            used by chunker to break data into discrete chunks.
            see specific chunkers for more information about this param.

用法示例:

>>> dr = pd.date_range(start='2010-01-01', periods=1000, freq='D')
>>> df = DataFrame(data={'data': np.random.randint(0, 100, size=1000),
                         'date': dr
                        })

>>> lib.write('symbol_name', df, chunk_size='M')

量化投资

发表于 2020-11-30 | 分类于 投资

关于量化投资的学习和思考

数学角度看量化

在量化投资单纯从数学角度看,一个交易系统/交易模型仅仅是一个从行情序列到资金曲线的映射。

f(ts,para) = E

其中f是一个交易系统,ts是某一个投资标的(股票、期货、期权、外汇等)的行情时间序列para是交易系统的参数组,E是资金曲线。

任何一个模型都会有参数,有参数就会碰到参数寻优,过拟合等问题。

参数优化是基于历史数据进行的策略优化。而历史并不能完全重演。历史中表现优秀的参数,在交易中未必会表现很好。

123…6
Airthink

Airthink

The Pursuit of Happyness

58 日志
20 分类
24 标签
GitHub
© 2018 - 2022 Airthink