- 投稿日:2020-07-06T21:04:01+09:00
FXトレーダーコミュニティをslackワークスペースで作った話(前編)
作ろうと思ったきっかけ
去年リリースされたLINEオープンチャット
他の興味も含め興味があるジャンルのオプチャにあちこち入った
そのうちの一つがFXのオプチャで
たまーに覗いていた程度だった。2月3月ごろコロナの影響で為替が大きく動いた時にちょっと
真剣に覗いてみたところトレンドの解説などをかなり詳しくやってくれている人が何人かいて
参考にトレードをしたりしていた。
しかし毎日オプチャを見ていると
いくつかの不自由さに気づく。
一つのタイムライン
まず一つはさまざまな話題が一個のタイムラインに溢れかえっていること
超初心者の自分でググれよみたいな質問だったり
だれかれ構わず粗探しをしたいクレーマー気質な人とそれと戦い続ける人の無駄なやりとりだったり
ロングしました、ショートしました!と張り切って伝えてくれている人がいるのはいいものの
ぱっと見でドル円の話をしているのかユーロポンドの話をしているのかが伝わりにくいかった。
職業柄かもしれないがこの情報が整理されていない状態がすごくストレスだった。
人間しか投稿できない煩わしさ
本業ではもちろんslackをバリバリ使うので当然アプリ連携なんか普通のことで
全部人間がPOSTしなければならないオプチャがすごく不便だった。そこで
これslackに移行できればすごく有意義な場所となるのでは?
という結論にいたり、作ってみました。
- 通貨ペアごとの部屋
- 話題ごとの部屋
- 簡単な通知bot
などを用意し
そこでオプチャで知り合った何人かに声をかけたのが始まり。vue.jsで作った公式サイト
https://fx-labo.web.app/
FX研究所公式オープンチャット
https://line.me/ti/g2/o1ChnqwNK5JtsE9FmAfvpgぶち当たる壁4つの壁
壁その1 slackって何?
おそらく既存の大多数のslackユーザーは
ITリテラシーが高めでslack以外のチャットツール(チャットワークなど)
を経験しており、さらには気兼ねなく不明点を聞ける会社の同僚といろいろ試しながら
slackに触れていったと思われる。ここの読者には信じられないかもしれないが
世間一般的にはslackの認知度なんて1割にも満たないと思われる
(コロナの影響で少しは上昇したかもだが)
その上、見ず知らずの相手に一からテキスト情報のみで
それを教えなければならないのだ
しかも、ITリテラシーが高いとはお世辞にも言えない人たちが大半だったため
グーグルで検索したり、とりあえず試してみたりという選択肢はなく
容赦無くどんどんチャット上で聞いてくる。しかもだいたい毎日同じ質問
(メンションはどうやってつけるの?スレッドって何?チャンネルって何?)FXの上手な人たちを集めて質の高いトレードのための情報を得ようと思ったのに
最初の二週間はほとんどCS(カスタマーサポート)のようなことばかりをしていた。
そして驚いたことに大半(感覚値8割強)がスマホのみでトレードもチャットも完結しているのだ.
筆者はプロジェクトでPCでslackを使うがスマホ版では確認と緊急の返信くらいしでしか使わないので
そこにズレが生じる。FXのトレーダーだーからみんなパソコンいっぱい持っていると思ってたが
パソコンの方が圧倒的少数派だった。壁その2 そこに性善説(優しい世界)はなかった
会社やプロジェクトでslackを使う時、最初にルールが共有されるだろう
general で雑談ばかりしていたり、チャンネル違いの投稿をするときっと誰かが指摘するだろう。
なぜなら会社プロジェクトを成功させるために効率化が必要という認識を
いつのまにか全員で共有できているからだしかしオンラインで集まった匿名コミュニティだと
FXで儲けたい人たちという共通項はあれど自分が損をしていなければ、
隣の人が100万円溶かしていようが関係ない話をしてようが全く関係ないのである
なので、他人のslack使い方がおかしかろうが、それを正さなければという意識が働かないのだ
慣れてきたらユーザー同士が優しく教えあう世界はそこにはなかった。今でこそ古参メンバーが管理人の苦労を汲み取っていろいろとサポートしてくれて(ほんと助かってる)
機能するようになったが開設当初はせっかく用意したチャンネルはほとんど機能せずほとんど雑談とチャンネル違いの話題で埋め尽くされていた。壁その3 自然流入がない
オプチャで勧誘してみたところ
開設一週間で50人以上の人が参加してくれた
しかし、そのうちアクティブに会話してくれたのは10人にも満たなかった。
オプチャだと1日に何十人もの人が検索経由で人が流入してくるが
Slackという閉ざされたコミュニティだとそれは皆無で
自分たちで外部で宣伝せざるを得ないのだが
なにせ、slackの認知度が低いため
よく分からん怪しいサイトに誘導してる奴がいるくらいの認識で終わってしまうのだ。
どうせ有料のサイトでしょ?なんか情報商材売りつけてくるんでしょ?と身構えてしまうのだ。
それに加えオプチャのルームにはそういった勧誘をを禁しているとこが大半なのだ
みんなであの手この手で勧誘していたら一番大きなFXのオプチャルームから締め出されてしまった。
その後twitterなどを駆使し別のユーザー獲得方法を確立(次回以降執筆予定)壁その4 Slackの無料枠の件
ユーザーの大半を雑談が多いオープンチャットから獲得していたのこともあるかもしれないが
FXは土日に相場は動かないので、土日には雑談チャンネルでみんなワイワイと話している。
(顔も名前もどこに住んでるのか年齢も分からない人たちとずっと為替の話をしているのが楽しい)一ヶ月半くらい経った時にslackのメッセージ数上限の通知がきた
(無料プランだと10000件を越えると古いものから表示されなくなる)
それは最初から知っていたし
そもそもFXの相場分析なので一週間も前の分析は必要ない、せいぜい2,3日分あれば十分なのだ
しかし10000件の容量のうち 通知系の垂れ流しbotと雑談でその大半を占めていることに気づいたのだ。
実況や即時性の情報ではなくナレッジを貯めていく系のチャンネルも用意していたのでこちらはいずれ消えるにせよ
できれば長く保存しておきたい。これらを少しでも延命させるために。
削除botを自作した。(詳しくは次回執筆予定)
雑談は300件以上増えると古いものから自動で削除
通知系垂れ流しは古い情報が不要なので10件
ドル円部屋は200件、テクニカルを教えあう部屋は500件
といった具合だ。
これにより10000件の枠をどのように分配するかある程度制御できるようになった。三ヶ月たった現在
上記のような紆余曲折があったが、
運用開始から三ヶ月経った今は ドル円やポンド円などメジャーな通貨ペアには常に誰かがいて
あーでもないこーでもないと相場を見守っているし、
類は友を呼ぶではないがエンジニアが多数集まってきており
最強のEA(自動トレードソフト)を開発しようという流れができてきたり。
上級者が初心者に優しく教えてあげるチャンネルが立ち上がったり。
土日には常連同士でくだらない雑談で盛り上がったりしている。当初想定していたコミュニティに少しずつ近づきつつある印象です。
最後に
次回以降、私が様々な便利ツールも並行して開発していますのでそのツールのご紹介もしますが
現時点で興味のある方
バリバリのトレーダーさんや
FXの初心者さん
自動トレードや機械学習トレードに興味があるエンジニアの方も
どなたでも無料で利用できますので参加希望の方は
オープンチャットかTwitterにて連絡いただければ招待URLをお知らせいたします。vue.jsで作った公式サイト
https://fx-labo.web.app/集客用twitter
https://twitter.com/FxSlack
- 投稿日:2020-07-06T16:43:58+09:00
Node.js でAWS Lambdaを量産する為のサンプルソースをgithubに公開してみた
AWS LambdaをNode.jsで量産アレコレ
概要
AWS LambdaをNode.jsで書こうと思ったときに、良く思うのが、、、
- AWS SDKがPromise前提で入れ子が深くなりがち
- 継承使って汎用共通処理とオーバーライド使いたいなぁ~
である。
コールドスタート対策などで、javaでの実装は圧倒的に不利ってことで、java屋がNode.jsでLambdaを書こうと思うと、
きっと同じ事を思うに違いない。(偏見)という事で、上記が出来る汎用ソースをgithubに公開してみました。
(参考投稿)
Lambdaのコールドスタートを改めて整理するindex.js の処理構造
として、業務処理を全て外だししてシンプルにする事で、汎用的なindex.jsにする。業務処理の処理構造
業務処理の継承ツリーは3階層でサンプルは書いてあります。
大体、3階層作ってあれば、大抵の業務は汎化できる。(これまた偏見)githubの公開場所
に置いてあります。
イメージ図は、別のサンプルですが、クリックする場所は一緒です。
ダウンロードしたZIPファイルを解凍すると、Lambda登録用のZipファイルが出てきますので、実行する場合は、それをLambdaとして登録してください。設定可能な環境変数
変数名 変数値 LogLevel ログの出力レベルを(0~4)までの間で設定する autoFunctionRetry 省略したらエラー時再実行はしない。0より大きい値(数字)を設定すると、その回数、再実行を行う 他サンプルソース
具体的な、
- API Gateway + Lambda + DynamoDB のサンプルソース
- DynamoDB Stream + Lambda + SNS のサンプルソース
などは、ブログにて公開中です。
- 投稿日:2020-07-06T10:47:30+09:00
Node.jsを使ったECS上でのTCPアプリケーションの構築
このチュートリアルでは、Alibaba Cloud ECSを使ってTCPクライアント/サーバのペアを作成し、Node.jsを使ってTCPアプリケーションを構築していきます。
本ブログは英語版からの翻訳です。オリジナルはこちらからご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。
Alibaba Cloud Tech Share執筆者のKunal Relanによるものです。Tech Shareは、クラウドコミュニティ内で技術的な知識やベストプラクティスを共有することを奨励するAlibaba Cloudのインセンティブプログラムです。
まず基本的なことから説明すると、オープンソースのJavaScriptランタイム環境として人気のあるものに、ChromeのV8 JavaScriptエンジン上に構築されたNode.jsがあります。Node.jsは主にサーバーサイドやネットワークアプリケーションの構築に使われています。TCP (Transmission Control Protocol) は、アプリケーション間でデータのストリームを信頼性の高い、順序立てられた、エラーチェックされた配信を可能にするネットワーキングプロトコルです。双方がデータストリームを交換するためには、TCPサーバがTCP接続要求を受け入れ、接続が確立されなければなりません。
TCP ソケットプログラムには、サーバとクライアントの 2 種類のプログラムを書くことができます。サーバの機能は、クライアントからの接続をリッスンし、処理されたデータを送り返すことです。この通信はソケットを介して行われます。
node.jsのTCPプログラミングにはnetという内部モジュールが必要で、ネットワークプログラミングの非同期ラッパーとして機能します。サーバとクライアントの構築にはAlibaba Cloud Elastic Compute Service (ECS)を使用します。
はじめに
このチュートリアルに従うためには、ubuntuやmacOSなどのlinux/unixディストリビューションが動作するマシン、コードエディタ/IDEのnode.jsがインストールされていること、node.jsの基本的な知識が必要です。このチュートリアルでは、アプリケーションを本番環境にデプロイするのではなく、開発用のマシンで実行し、そこからテストを行います。
TCPサーバの作成
まず、アプリケーションを保存するディレクトリを作成します。このチュートリアルでは、
~/nodejs-tcp-app
にアプリケーションを作成します。このチュートリアルでは、ほとんどの作業をターミナルで行います。また、ターミナルで
nano
エディタを使用して、すべてのプラットフォームで同じプロセスを保証します。開始するには、ターミナルを開きます。
mkdir ~/nodejs-tcp-appさて、新しく作成したディレクトリに切り替えて、
npm init
を実行してpackage.jsonファイルを作成します。cd ~/nodejs-tcp-app && npm initこれでターミナルからプロジェクトの基本情報を聞かれるので、
server.js
として名前、作者、メインファイルを追加してファイルを作成します。これでディレクトリ内にpackage.json
ファイルが表示されるはずです。次に、TCPサーバのコードを含む
server.js
ファイルを作成します。同じディレクトリに以下のコマンドを入力して、
server.js
ファイルを作成し、テキストエディタを開いてコードを書きます。nano server.jsまず、node.jsに同梱されている
net
モジュールをインポートし、サーバーを実行するポートとホストを定義して、サーバーのインスタンスを作成します。const net = require('net'); //define host and port to run the server const port = 8080; const host = '127.0.0.1'; //Create an instance of the server const server = net.createServer(); //Start listening with the server on given port and host. server.listen(port,host,function(){ console.log(`Server started on ${host}:${port}`); });これはアプリケーションの基本的な構成要素であり、TCP サーバを起動するのに十分なものです。
次に、クライアントが接続する接続にリスナーを追加する必要があります。
サーバの宣言を編集して、
onClientConnection
という接続リスナー関数を追加し、下部に関数を宣言します。const net = require('net'); //define host and port to run the server const port = 8080; const host = '127.0.0.1'; //Create an instance of the server const server = net.createServer(onClientConnection); //Start listening with the server on given port and host. server.listen(port,host,function(){ console.log(`Server started on port ${port} at ${host}`); }); //Declare connection listener function function onClientConnection(sock){ //Log when a client connnects. console.log(`${sock.remoteAddress}:${sock.remotePort} Connected`); //Listen for data from the connected client. sock.on('data',function(data){ //Log data from the client console.log(`${sock.remoteAddress}:${sock.remotePort} Says : ${data} `); //Send back the data to the client. sock.write(`You Said ${data}`); }); //Handle client connection termination. sock.on('close',function(){ console.log(`${sock.remoteAddress}:${sock.remotePort} Terminated the connection`); }); //Handle Client connection error. sock.on('error',function(error){ console.error(`${sock.remoteAddress}:${sock.remotePort} Connection Error ${error}`); }); };そこで、onClientConnection関数では、接続オブジェクトの
sock
を期待して、data
、close
、error
の3つのイベントリスナーを作成します。データイベントリスナーでは、クライアントから受信した
data
をコンソールログに記録してクライアントに送信し、close
イベントリスナーでは、接続の終了を処理してコンソールログに記録します。error
イベントリスナーはクライアントからの接続エラーを処理します。これで
server.js
のコードが完成し、これで TCP クライアントの接続を受け入れ、それらのデータをリッスンしてクライアントにエコーバックする TCP アプリケーションが動作するようになりました。ファイルを保存してnanoエディタを終了します。同じモジュールを使って TCP クライアントを作成してみましょう。
TCP クライアントの作成
nanoコマンドを使って
client.js
ファイルを作成し、作業を開始してみましょう。nano client.js
server.js
でやったように、netモジュールをインポートして引数を定義してみましょう。const net = require('net'); //define the server port and host const port = 8080; const host = '127.0.0.1'; //Create an instance of the socket client. const client = new net.Socket(); //Connect to the server using the above defined config. client.connect(port,host,function(){ console.log(`Connected to server on ${host}:${port}`); //Connection was established, now send a message to the server. client.write('Hello from TCP client'); }); //Add a data event listener to handle data coming from the server client.on('data',function(data){ console.log(`Server Says : ${data}`); }); //Add Client Close function client.on('close',function(){ console.log('Connection Closed'); }); //Add Error Event Listener client.on('error',function(error){ console.error(`Connection Error ${error}`); });これで
client.js
はサーバーに接続し、接続時にメッセージを送信し、サーバーからのレスポンスをログに記録します。ここでもサーバと同様に、データ、接続終了、接続エラーを処理するための3つのイベントリスナーを追加しています。
ファイルを保存して
nano
エディタを終了します。接続のテスト
TCPベースのサーバとクライアントアプリの作成が完了したので、サーバを起動してTCPクライアントをサーバに接続する必要があります。
このためには、2つのターミナルセッションが必要です-1つはサーバ用、もう1つはクライアント用です。
最初のセッションでは、次のコマンドを使用してサーバを起動します。
node server.jsこのコマンドはTCPサーバを起動し、ターミナルにログが表示されるはずです。
Server started on 127.0.0.1:8080次に、サーバーに接続してメッセージを送信するためにTCPクライアントファイルを起動する必要があります。別のターミナルで次のコマンドを入力します。
node client.jsこれでTCPクライアントが起動し、サーバに接続してメッセージを送信しようとします。さて、あなたのターミナルには次のようなテキストが表示されているはずです。
Connected to server on 127.0.0.1:8080 Server Says : You Said Hello from TCP clientこれで、クライアントがサーバに接続できて、ログを記録できるエコーを受信したことがわかりました。
次に、サーバを実行しているターミナルセッションに戻ると、このように表示されるはずです。ただし、クライアントのポートは異なる場合があります。
127.0.0.1:56330 Connected 127.0.0.1:56330 Says : Hello from TCP clientプログラムでクライアント接続を閉じるわけではないので、close イベントリスナーはトリガーされません。しかし、クライアント端末に戻って ^c を押すと、クライアントは終了し、サーバ端末では接続終了のログを取得することができます。
127.0.0.1:56330 Terminated the connectionTCPサーバとクライアントのテストに成功しました。
結論
このチュートリアルでは、Alibaba Cloud Elastic Compute Service (ECS)インスタンス上でNode.jsを使ってTCPアプリケーションを作成しました。TCPソケットを使ってもっと多くのことができますが、これはその入門的なプログラムでした。これの高度なバージョンでは、TCPサーバを介してメッセージの送受信を可能にするチャットルームにすることができます。また、リアルタイムのデータ通信のための大きなデータストリームの塊を処理するために使用することもできます。
アリババクラウドは日本に2つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
アリババクラウドジャパン公式ページ
- 投稿日:2020-07-06T10:40:17+09:00
GithubのissueをAPI経由で作成する
issue管理大変ですよね。
複数のissueを一気に登録したり、システムと連携してイベントベースでissueを登録できたりすると、issueを管理するのがずっと楽になります。
node.jsで実装しているので、AWS Lambda経由で実行するといろんなイベントから呼び出せて汎用性が高そうです。
使うもの
octkitというGithubAPIクライアントのライブラリを使います。
https://developer.github.com/v3/libraries/ドキュメントも豊富で使いやすいです。
実装
create_issue.jsconst { Octokit } = require("@octokit/rest"); const dotEnv = require('dotenv').config(); const octokit = new Octokit({auth: dotEnv.parsed.ACCESS_TOKEN}); if (process.argv.length !== 4) { console.log('タイトルと本文を指定して下さい'); return; } octokit.issues.create({ owner: '組織名', repo: 'リポジトリ名', title: process.argv[2], body: process.argv[3], }).then(({data}) => { console.log(data); }).catch(error => { console.log(error); });dotenvを使ってACCESS_TOKENを外から渡せるようにしてあります。
.envACCESS_TOKEN=アクセストークンこれでissueを作成できます。
- 投稿日:2020-07-06T03:10:23+09:00
Node.js + Express + PhpStormでWordpressの投稿をWP REST APIを使って表示する
PhpStormでNode.js Express Appを新規作成
File -> NewProject -> Node.js Express App
この時のオプションは以下の通りです。
Options
- View Engine: EJS
- Stylesheet Engine: Plain CSSterminalで WP APIをインストール
npm install wpapi --saveroutes/index.jsを編集
var express = require('express'); var router = express.Router(); var WPAPI = require( 'wpapi' ); var wp = new WPAPI({ endpoint: 'https://localhost/my-local-test/wp-json/' }); /* GET home page. */ router.get('/', function(req, res, next) { wp.posts().then((posts) => { console.log(posts); res.render('index', { title: 'Express' }); }); }); module.exports = router;エンドポイントを登録して、
var wp = new WPAPI({ endpoint: 'https://localhost/my-local-test/wp-json/' });getリクエストの処理を書きます。
router.get('/', function(req, res, next) { wp.posts().then((posts) => { console.log(posts); res.render('index', { title: 'Express' }); }); });ローカル環境では取れましたが、やりたいサイトではエラーがー出てしまってます。
(node:25928) UnhandledPromiseRejectionWarning: TypeError: Cannot create property '_paging' on string '' at returnBody (C:\Users\Koji\PhpstormProjects\wordpress-api-test\node_modules\wpapi\lib\http-transport.js:244:16) at processTicksAndRejections (internal/process/task_queues.js:93:5) (node:25928) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1) (node:25928) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
今日はここまで。