brew install libjpeg
pip install Pillow
Author Archives: toanalien
psycopg2 on mac m1
brew install postgresql
brew link openssl
export CPPFLAGS="-I/opt/homebrew/opt/openssl@1.1/include"
export LDFLAGS="-L/opt/homebrew/opt/openssl@1.1/lib"
pip install psycopg2
Install TA-lib in Google Colab
wget http://prdownloads.sourceforge.net/ta-lib/ta-lib-0.4.0-src.tar.gz && \
tar -xzf ta-lib-0.4.0-src.tar.gz && \
cd ta-lib/ && ./configure --prefix=/usr && make && sudo make install
pip install TA-lib
ref: https://mrjbq7.github.io/ta-lib/install.html
Đọc biến môi trường từ file

Theo Nguyên tắc số 3 của The Twelve-Factor App thì cấu hình cần phần tách biệt khỏi source code.
Thông thường cấu hình sẽ được lưu ở biến môi trường hoặc một dịch vụ bên ngoài như AWS Secrets Manager.
Trong Golang, để đọc biến môi trường ta có thể sử dụng code bên dưới
// set biến môi trường
os.Setenv(key, value)
// get biến môi trường
value := os.Getenv(key)
Để đọc biến môi trường được cấu hình từ file (ví dụ như .env
) thì ta có thể sử dụng package godotenv
godotenv
go get github.com/joho/godotenv
godotenv
cung cấp phương thức Load
để đọc file env
// mặc định đọc file .env ở trong thư mục hiện tại
godotenv.Load()
// hoặc chỉ định file
godotenv.Load("/path/to/file/env")
File env hỗ trợ format yaml
, tham khảo tài liệu ở đây
viper
Ngoài godotenv
thì viper
là package phổ biến nhất hỗ trợ các format như JSON, TOML, YAML, HCL, envfile và cả Java properties config file.
go get github.com/spf13/viper
// cấu hình đường dẫn file env
viper.SetConfigFile(".env")
// đọc cấu hình
viper.ReadInConfig()
// đọc giá trị
viper.Get(key)
// xác nhận kiểu dữ liệu
value, ok := viper.Get(key).(string)
// nếu kiểu dữ liệu của `key` là string thì ok trả về true
5 lời khuyên đầu tư với tài khoản nhỏ
Khi bắt đầu giao dịch chúng ta muốn kiếm được nhiều tiền và trở thành tỉ phí vào cuối tháng. Động lực tuyệt vời này có thể bị cắt bỏ dễ dàng nếu không tuân thủ theo chiến lược và kế hoạch đơn giản.
Khi tôi bắt đầu giao dịch tôi vào 100$ và mất tất cả chỉ trong tháng. Tôi đã không chú ý đến kế hoạch và quy tắc tài chính cá nhân của mình, điều này khiến tôi thua lỗ rất nhiều trong những bước đầu tiên tham gia giao dịch.
Biết 5 mẹo này sẽ giúp ích cho bạn nếu bạn mới bắt đầu giao dịch và sử dụng tài khoản nhỏ.
1. Thực hiện theo kế hoạch tài chính, KHÔNG BAO GIỜ ALL-IN.
Vâng, để lập kế hoạch tài chính, bạn cần phải nghiên cứu nó trước, nếu bạn không có kiến thức về tài chính. ĐỪNG ALL-IN, đây không phải là trò đùa, hãy dừng lại ngay! NHỎ hay LỚN cũng như nhau trong giao dịch, và hãy xem các giao dịch của bạn một cách cẩn thận.
2. Dùng ít công cụ hơn, giảm số lượng giao dịch.
HÃY TẬP TRUNG. Một lần nữa, ÍT cũng như NHIỀU, NHỎ cũng như LỚN. Tìm hiểu một hoặc hai loại tài sản, tìm hiểu bản chất của chúng và hành vi biểu đồ thông thường. Điều này sẽ giúp bạn tập trung và bắt đầu mở các giao dịch có lãi.
3. Tránh các tài sản biến động mạnh; Giao dịch tài sản có khối lượng lớn.
Chọn một hoặc hai loại tài sản có khối lượng giao dịch lớn, chỉ nên giao dịch mỗi chúng. Đừng tiền vào cổ phiếu hoặc ngoại tệ chỉ vì chúng có giá thấp.
4. Sử dụng khung thời gian cao hơn, không scalping.
Hầu hết các nhà giao dịch mới đều mất tiền trong những tháng đầu tiên chỉ vì họ cố gắng mở rộng quy mô, cảm xúc của bạn trở nên điên cuồng và rủi ro tăng lên nhanh chóng. Bắt đầu thực hiện một-hai giao dịch mỗi tuần và xem nó sẽ diễn ra như thế nào, điều này sẽ giải phóng áp lực và thư giãn.
5. Chấp nhận thua lỗ, lên kế hoạch có thể mất bao nhiêu.
Vấn đề lớn nhất của tất cả các nhà giao dịch là suy nghĩ theo tỷ lệ phần trăm về tổn thất, cách này sẽ chỉ làm tăng tổn thất. Hãy suy nghĩ về tiền bạc và lập kế hoạch cho bạn số tiền thua lỗ có thể chấp nhận được.
Chú thích
- Scalping: Scalping – Scalp hay Scalper trong Trading đều là thuật ngữ dùng để biểu thị những phương pháp lướt sóng để thu lợi nhuận nhỏ một cách thường xuyên, bằng cách vào và thoát lệnh nhiều lần trong ngày. https://traderviet.com/threads/scalping-la-gi-huong-dan-cach-scalping-trong-thi-truong-forex.5515/
Nguồn bài viết https://www.tradingview.com/chart/BTCUSD/cL1mUIVQ-5-TIPS-FOR-SMALL-ACCOUNTS/
Clean empty folder in MacOS
TL;DR:
find . -name .DS_Store -delete
find . -type d -empty -delete
Ref: https://apple.stackexchange.com/questions/79391/locate-empty-folders-within-a-folder#comment91730_79406
Golang on M1
Lỗi
Failed to launch: could not launch process: can not run under Rosetta, check that the installed build of Go is right for your CPU architecture
Nguyên nhân
Do package dlv
và dlv-dap
sai architecture trên M1.
Khắc phục
- Kiểm tra phiên bản Golang đã cài đặt đúng chưa bằng cách
go env | grep GOARCH
# GOARCH="arm64"
Nếu phiên bản là arm64
trên M1 là đúng, nếu khác thì cần phải cài đặt lại. Download ở đây https://golang.org/dl/

Tiếp theo mở VSCode, gõ Shift + Command + P
tìm "Go: Install/Update Tools"
, click vào dlv
và dlv-dap
chọn ok để install/update.

Bây giờ mở lại debug (Shift + Command + D) sẽ chạy được như ý muốn.

Quản lý phiên bản Node.js

Mình dùng NVM để cài đặt Node.js và có thể chọn được version cần dùng.
Cài đặt
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash
export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
Show danh sách các phiên bản Node.js lts
nvm ls-remote --lts
...
v12.21.0 (LTS: Erbium)
v12.22.0 (LTS: Erbium)
v12.22.1 (LTS: Erbium)
v12.22.2 (LTS: Erbium)
v12.22.3 (LTS: Erbium)
v12.22.4 (LTS: Erbium)
v12.22.5 (Latest LTS: Erbium)
v14.15.0 (LTS: Fermium)
v14.15.1 (LTS: Fermium)
v14.15.2 (LTS: Fermium)
v14.15.3 (LTS: Fermium)
v14.15.4 (LTS: Fermium)
v14.15.5 (LTS: Fermium)
v14.16.0 (LTS: Fermium)
v14.16.1 (LTS: Fermium)
v14.17.0 (LTS: Fermium)
v14.17.1 (LTS: Fermium)
v14.17.2 (LTS: Fermium)
v14.17.3 (LTS: Fermium)
v14.17.4 (LTS: Fermium)
-> v14.17.5 (Latest LTS: Fermium)
Cài đặt Node.js. Npm sẽ đi kèm
nvm install v14.17.5
v14.17.5 is already installed.
Now using node v14.17.5 (npm v6.14.14)
Calculate MA, SMA indicators in Pandas
Tiếp theo bài viết https://toan.co/prepare-dataset-for-backtest-strategy/ mình sẽ tính các chỉ số SMA, EMA trên Pandas
df['SMA7'] = df.Close.rolling(5).mean()
df['SMA14'] = df.Close.rolling(14).mean()
df['EMA10'] = df.Close.ewm(span=10, adjust=False).mean()
df['EMA20'] = df.Close.ewm(span=20, adjust=False).mean()
# plot
df.head(500)[['SMA7', 'SMA14', 'EMA10', 'EMA20']].plot(figsize=(15, 10))

Confluent Docker in M1
TL;DR:
- Vì bản docker build sẵn của Confluent cung cấp chỉ chạy được trên amd64 nên để chạy được mình cần build bản riêng cho arm64.
- Nếu build lại từ đầu bằng cách lấy base image là arm64 rồi install thì tốn công hơn nên mình mod lại bản build của Confluent. Code trong repo bên dưới.
git clone https://github.com/toanalien/cp-docker-images.git
cd cp-docker-images
git checkout v6.2.0
make build-debian
Sample docker-compose.yaml file
---
version: '2'
services:
zookeeper:
image: confluentinc/cp-zookeeper:6.2.0
hostname: zookeeper
container_name: zookeeper
ports:
- "2181:2181"
environment:
ZOOKEEPER_CLIENT_PORT: 2181
ZOOKEEPER_TICK_TIME: 2000
broker:
image: confluentinc/cp-server:6.2.0
hostname: broker
container_name: broker
depends_on:
- zookeeper
ports:
- "9092:9092"
- "9101:9101"
environment:
KAFKA_BROKER_ID: 1
KAFKA_ZOOKEEPER_CONNECT: 'zookeeper:2181'
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://broker:29092,PLAINTEXT_HOST://localhost:9092
KAFKA_METRIC_REPORTERS: io.confluent.metrics.reporter.ConfluentMetricsReporter
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0
KAFKA_CONFLUENT_LICENSE_TOPIC_REPLICATION_FACTOR: 1
KAFKA_CONFLUENT_BALANCER_TOPIC_REPLICATION_FACTOR: 1
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
KAFKA_JMX_PORT: 9101
KAFKA_JMX_HOSTNAME: localhost
KAFKA_CONFLUENT_SCHEMA_REGISTRY_URL: http://schema-registry:8081
CONFLUENT_METRICS_REPORTER_BOOTSTRAP_SERVERS: broker:29092
CONFLUENT_METRICS_REPORTER_TOPIC_REPLICAS: 1
CONFLUENT_METRICS_ENABLE: 'true'
CONFLUENT_SUPPORT_CUSTOMER_ID: 'anonymous'
schema-registry:
image: confluentinc/cp-schema-registry:6.2.0
hostname: schema-registry
container_name: schema-registry
depends_on:
- broker
ports:
- "8081:8081"
environment:
SCHEMA_REGISTRY_HOST_NAME: schema-registry
SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: 'broker:29092'
SCHEMA_REGISTRY_LISTENERS: http://0.0.0.0:8081
control-center:
image: confluentinc/cp-enterprise-control-center:6.2.0
hostname: control-center
container_name: control-center
depends_on:
- broker
- schema-registry
ports:
- "9021:9021"
environment:
CONTROL_CENTER_BOOTSTRAP_SERVERS: 'broker:29092'
CONTROL_CENTER_CONNECT_CONNECT-DEFAULT_CLUSTER: 'connect:8083'
CONTROL_CENTER_KSQL_KSQLDB1_URL: "http://ksqldb-server:8088"
CONTROL_CENTER_KSQL_KSQLDB1_ADVERTISED_URL: "http://localhost:8088"
CONTROL_CENTER_SCHEMA_REGISTRY_URL: "http://schema-registry:8081"
CONTROL_CENTER_REPLICATION_FACTOR: 1
CONTROL_CENTER_INTERNAL_TOPICS_PARTITIONS: 1
CONTROL_CENTER_MONITORING_INTERCEPTOR_TOPIC_PARTITIONS: 1
CONFLUENT_METRICS_TOPIC_REPLICATION: 1
PORT: 9021
rest-proxy:
image: confluentinc/cp-kafka-rest:6.2.0
depends_on:
- broker
- schema-registry
ports:
- 8082:8082
hostname: rest-proxy
container_name: rest-proxy
environment:
KAFKA_REST_HOST_NAME: rest-proxy
KAFKA_REST_BOOTSTRAP_SERVERS: 'broker:29092'
KAFKA_REST_LISTENERS: "http://0.0.0.0:8082"
KAFKA_REST_SCHEMA_REGISTRY_URL: 'http://schema-registry:8081'