以下在Python 2.7,MacOS上试过
f = open('ctrla.txt', 'w') f.write('abc') f.write(u'\u0001') f.write('35') f.close()
vim ctrla.txt
1 abc^A35
程序|生活
以下在Python 2.7,MacOS上试过
f = open('ctrla.txt', 'w') f.write('abc') f.write(u'\u0001') f.write('35') f.close()
vim ctrla.txt
1 abc^A35
在美国当home owner,就总会碰到这样或那样的问题。爆水管就是其中一项。这不,今天就碰到了。我家前院的一个水龙头因为老化,直接就给冲喷了。前院直接就水漫金山了。而且祸不单行的是,那个总闸好像还坏了。我还算镇静,想到水表那应该有开关。结果发现那个开关是个长条形的,根本拧不动。只好打电话给当地自来水公司。幸好我们的墨西哥邻居出手相助,用了一个超大的扳手给关上了。因为自来水公司他们只来帮关闸,不管维修,所以就再打电话给他们说不用来了。他们反应很慢,不知道还要等几个小时呢。
后来我买来新的水龙头换上,但是邻居不在,总不能老麻烦人家。如果Google了一下这个阀门应该有什么工具。结果还真给我找到了。这个工具叫water meter key
如果家里curb side的水表的阀门是这种长条类型的,强烈建议花10几刀给家里备上这么个救命神器。真到爆水管的关键时候能把总闸关了。叫一次plumber起码得几百刀了,而且要多少你都得给。我不知道叫自来水公司要不要钱,这次我是取消了,不然说不定事后给张账单也说不准。
一般在Java里,我们可以用printStackTrace把stacktrace打印出来。
try { // do something } catch (Exception e) { e.printStackTrace(); }
在server里,如果我们需要用graylog来search log,就需要把stacktrace压缩到一行。我们可以用apache的ExceptionUtils
import org.apache.commons.lang.exception.ExceptionUtils; //... try { // do something } catch (Exception e) { logger.error("Exception: {}", ExceptionUtils.getStackTrace(e) ); }
在我的Macbook上写中文,标点符号都是半角的(也就是英文的)。一直都很疑惑,本来还以为是wordpress的问题。今天好奇在网上做了一下研究,终于找到原因了。
点击屏幕上方的菜单栏的输入法
注意下拉菜单里面有个“Use Halfwidth Punctuation“的选项,如果这个是打勾的,就会用半角标点符号。再点击一下去掉勾就可以变会正常的全角中文标点符号了。
最近遇到一个问题,用Excel打开含有韩语CSV文件, 里面的韩语字符都是乱码。后来发现问题是那些CSV的encoding格式是UTF-8。如果直接用Excel打开,解码格式就不对。
解决方法
在File目录选import
选CSV
选择文件,然后重要的一步, 选择File origin,然后选UTF-8
剩下的正常操作, 选择delimiter,这样韩语(其实是任何 UTF-8的字符)就可以在Excel正常显示了。
前段一直是我的短板, 没有太多机会系统学习. 最近想做一个股票分析系统的webapp, 于是就在网上找合适的javascript library做data visualization. D3.js以前用过, 觉得太过底层, 写起来太麻烦. 于是发现了ECharts, 好像是国内大神写得, 已经是Apache project, 非常厉害. 于是follow了这个tutorial. 里面有些小细节我觉得初学者可能会卡住, 这里我写得详细一点.
npm是node package manager的意思, 是用了管理安装javascript libraries的. 相当于Python里的pip. 安装可以看我前面的文章.
首先给项目建立一个新的directory
% mkdir test_echart
% cd test_echart
在项目directory里安装echarts library
npm install echarts --save
完成后directory里会有那么几个东西
% ls
package-lock.json
node_modules/ package.json
在项目directory里面添加一个html file叫main.html, 内容如下调用echart
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <!-- including ECharts file --> <script src="node_modules/echarts/dist/echarts.min.js"></script> </head> <body> <!-- preparing a DOM with width and height for ECharts --> <div id="main" style="width:600px; height:400px;"></div> </body> <script type="text/javascript"> // based on prepared DOM, initialize echarts instance var myChart = echarts.init(document.getElementById('main')); // specify chart configuration item and data var option = { title: { text: 'ECharts entry example' }, tooltip: {}, legend: { data:['Sales'] }, xAxis: { data: ["shirt","cardign","chiffon shirt","pants","heels","socks"] }, yAxis: {}, series: [{ name: 'Sales', type: 'bar', data: [5, 20, 36, 10, 10, 20] }] }; // use configuration item and data specified to show chart myChart.setOption(option); </script> </html>
header里面的这行相当于Python的import
<script src="node_modules/echarts/dist/echarts.min.js"></script>
现在directory内容如下
% ls
main.html package-lock.json
node_modules/ package.json
用浏览器打开main.html. 在Mac里可以在terminal里用
% open main.html
网页显示如下, 还是挺酷的.
简单看看js code, option就是一个json object, 里面包含了图的一些信息和data. 一开始init了一个echarts object, 然后给它set一下option这个json object. 和d3比起来还是简单多了.
var myChart = echarts.init(document.getElementById('main')); var option = { // json object }; myChart.setOption(option);
我把数据改一改, 就可以显示一些投资标的的市值了
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <!-- including ECharts file --> <script src="node_modules/echarts/dist/echarts.min.js"></script> </head> <body> <!-- preparing a DOM with width and height for ECharts --> <div id="main" style="width:1000px; height:400px;"></div> </body> <script type="text/javascript"> // based on prepared DOM, initialize echarts instance var myChart = echarts.init(document.getElementById('main')); // specify chart configuration item and data var option = { title: { text: 'Market Caps' }, tooltip: {}, legend: { data:['Sales'] }, xAxis: { data: [] }, yAxis: {}, series: [{ name: 'Sales', type: 'bar', data: [] }] }; const MARKET_CAP = 'market cap'; var legends = [MARKET_CAP]; var symbols = ['AAPL', 'GOOGL', 'FB', 'AMZN', 'NVDA', 'NFLX', 'TSLA', 'BTC', 'ETH', 'V', 'MA'] var marketCaps = [2256, 1185, 778, 1634, 323, 238, 669, 622, 109, 482, 356]; option.legend.data = legends; option.xAxis.data = symbols; option.series[0].data = marketCaps; option.series[0].name = MARKET_CAP; // use configuration item and data specified to show chart myChart.setOption(option); </script> </html>
网页更新如下. 接上个数据的后端就可以显示不同的数据了.
Node官网下载安装包(pkg文件)
正常双击安装下载下来的pkg文件, 最后一步还会告诉你装哪了. 可见node和npm都放在/user/local/bin
里了.
% node -v
v15.5.0
% npm -v
7.3.0
Pandas是一个非常强大的数据分析方面的Python package. 如果是做Machine Learning或者数据分析, 掌握Pandas很省去很多麻烦. 许多Machine Learning前期的数据处理也是用Pandas做得.
IBKR(Interactive Brokers, 有时简称IB, 中文叫盈透证券)是美国老牌券商, 也是我的主要使用的券商. 又到了辞旧迎新的时候, 需要看看2020投资收益, 于是趁新年长周末写点小程序做点数据分析. 而这正好覆盖了Pandas的各种常用functions.
IB Statement提供多种方式下载, 比如html, pdf, csv. 用作数据处理选csv. 内容大概长这样
Statement这个column是内容, 里面有很多项, 而这里我只看“Realized & Unrealized Performance Summary”, 然后相同的第一列后面的列数都是一样的. 上图是Jupyter Lab的显示有问题. 因为文件其实可以看成很多CSV files连在一起, 而第一列可以看成是小csv的文件名. 然后第二列是Header或者Data. Header那行就是告诉你后面的Data行里每一列都是什么. 于是我们可以把数据读到内存里.
import pandas as pd field = 'Realized & Unrealized Performance Summary' f = open('statement.csv', 'r') rows = [] for line in f: cols = line.strip().split(',') if cols[0] == field: if cols[1] == 'Header': header_row = cols[2:] else: rows.append(cols[2:])
header_ros是个list of string
['Asset Category', 'Symbol', 'Cost Adj.', 'Realized S/T Profit', 'Realized S/T Loss', 'Realized L/T Profit', 'Realized L/T Loss', 'Realized Total', 'Unrealized S/T Profit', 'Unrealized S/T Loss', 'Unrealized L/T Profit', 'Unrealized L/T Loss', 'Unrealized Total', 'Total', 'Code']
而rows是list of list. 就是list of rows
[['Stocks', 'AAPL', '0', '0', '0', '0', '0', '0', '29564.510608', '-14.176325', '0', '0', '29550.334283', '29550.334283', '\n'], ['Stocks', 'AMD', '0', '0', '0', '0', '0', '0', '220.208447', '0', '0', '0', '220.208447', '220.208447', '\n'], ... ]
接下来就可以用Panda create dataframe了
df = pd.DataFrame(rows, columns = header_row) df.head(5)
这里有个问题. Created出来的dataframe的数据类型有数字有string, 全部都是object. 如果sort by数字column得到的结果是sort by string, 并不是我们想要的. 可以用dtypes来确定
df.dtypes
Asset Category object Symbol object Cost Adj. object Realized S/T Profit object Realized S/T Loss object Realized L/T Profit object Realized L/T Loss object Realized Total object Unrealized S/T Profit object Unrealized S/T Loss object Unrealized L/T Profit object Unrealized L/T Loss object Unrealized Total object Total object Code object dtype: object
这里我把需要转换成数字的columns转换了
header_text_col = set(['Asset Category', 'Symbol', 'Code']) num_col = list(set(header_row) - header_text_col) df[num_col] = df[num_col].apply(pd.to_numeric) df.dtypes
Asset Category object Symbol object Cost Adj. int64 Realized S/T Profit float64 Realized S/T Loss float64 Realized L/T Profit int64 Realized L/T Loss float64 Realized Total float64 Unrealized S/T Profit float64 Unrealized S/T Loss float64 Unrealized L/T Profit int64 Unrealized L/T Loss float64 Unrealized Total float64 Total float64 Code object dtype: object
这样就可以对数字类型的column进行排序了, 比如下面指令做2步操作
1. 选出Asset Category是”Stocks”的rows, 相当于SQL里的where, 语法为df[df['Asset Category'] == 'Stock']
, return是另一个filtered好的dataframe
2. 按Realized Total从小到大排序, return也是另一排序好的dataframe
df[df['Asset Category'] == 'Stock'].sort_values(by=['Realized Total'], ascending=True)
还可以画图
stock_gain = df[ (df['Asset Category'] == 'Stocks') & ( df['Realized Total'] != 0.0)][['Symbol', 'Realized Total']].sort_values( by=['Realized Total'], ascending=True) stock_gain
还可以画图
stock_gain.plot.bar(x='Symbol')
rows是list of rows(lists), header_row是list of string
df = pd.DataFrame(rows, columns = header_row)
df.head(10)
df.tail(10)
num_col是list of strings, 下面命令会把num_col里的columns都转化成数字类. 类似SQL里的select cast(col1 as double), cast(col2 as double), ... from df
df[num_col] = df[num_col].apply(pd.to_numeric)
类似SQL里, select * from df where asset_category = 'Stocks' order by realized_total asc;
df[df['Asset Category'] == 'Stocks'].sort_values(by=['Realized Total'], ascending=True)
原来以为这个问题很简单, Google了一下发现网上的答案五花八门, 而且版本很混乱 有httpd的, ASP.net, url redirect的, url rewrite的. 经过多次尝试各种组合, 终于试出了一个可行的解决方案, 值得在此记录一下, 相信一定能帮到有类似需求的人. 本文例子为Ubuntu + apache2, 2020年, 2021年左右.
编辑/etc/apache2/sites-available里面的一个site, 比如mysite, 需要redirect到anothersite.com, 那么可以加上一行Redirect
<VirtualHost *:80>
ServerAdmin webmaster@localhost
...
ServerName mysite.com
ServerAlias www.mysite.com
DocumentRoot /var/www/html/mysite
Redirect / http://anothersite.com
...
修改完成后保存, 重启apache2
sudo service apache2 restart
上面的方法可以redirect到不同的URL, 但是如果想redirect mysite.com到mysite.com/blog就不行. 我试了一下, 如果像上面那样改动, 在浏览器输入mysite.com就会被不停的改成mysite.com/blog/blog/blog… 无限循环. 很明显, 改写是recursive的. 那么就不要用Redirect而是用RedirectMatch
<VirtualHost *:80>
ServerAdmin webmaster@localhost
...
ServerName mysite.com
ServerAlias www.mysite.com
DocumentRoot /var/www/html/mysite
RedirectMatch ^/$ /blog/
...
我也不太清楚apache2配置的语法细节, 但是以上是试过可行的方法. 最后一样是重启apache2让配置生效
sudo service apache2 restart
牛年还没到, 最近比特币就已经气冲天, 今天单价已经过了$26,000. 因为Concoinbase Pro有一次交易最少要买0.001个比特币的限制, 入场门槛越来越高了, 现在最少一次也要买入$26.xx以上了. 今天以前总投入$60, holding总价值$86.xx, 不到一个月总回报43%! 如果把全部资产买入真的是有机会改变阶级. 不过能赚到不正是因为赌注下少, 不在乎它的短期波动, 所以才能拿的住吗?我觉得还是继续执行定投计划, 也许会适量增加一点投入, 但注码量要控制在即使输光也不会让自己难受的范围内, 毕竟这还是有可能归零的高风险投资, 而自己对比特币还并不是很熟悉, 有时间的时候还是要多学习, 或者能做为程序员参与到相关项目开发中, 这样才有信心下比较重的注码投入. 不然就还是以娱乐为主吧.
今天新投入$30, 买入0.00111758, 均价$26,710.00. 总投入$90, holding现价值116.10.