Pythonで為替のテクニカル指標を可視化

はじめまして、2017年新卒システムエンジニアの鈴木です。
6月から解析ユニットに配属され、現在は広告の分析業務をしています。
解析ユニットはとても良い所です。

今回は、Pythonを用いて為替のテクニカル指標を簡単にプロットする方法を紹介したいと思います。

準備

為替情報の取得には、OANDA社の提供するREST-V20 APIを使います。

https://www.oanda.com/

こちらのウェブサイトからデモトレード用の口座を開設することで、APIを利用するためのアクセストークンを取得することができます。

APIのラッパーと、データ操作・可視化用のライブラリを導入します。

pip install oandapyV20
pip install pandas
pip install matplotlib
pip install seaborn

以上で準備完了です。

データ取得

実際に為替データを取得してみます。
今回はドル円1分足のローソク足データを1時間分取ります。

ローソク足とは
単位時間あたりの始値、高値、安値、終値の4つで構成される指標です。
単位時間によって1分足、1時間足、日足という呼び方をします。
足を「あし」と呼びます。

candlestick.py

import datetime
import pandas
import seaborn
import matplotlib.pyplot as plt
from matplotlib.finance import candlestick_ohlc as plot_candle
from oandapyV20 import API
import oandapyV20.endpoints.instruments as oandapy

if __name__ == '__main__':
    now          = datetime.datetime.now() - datetime.timedelta(hours = 9) # 標準時に合わせる
    minutes      = 61 # 60分取得
    time_min     = now - datetime.timedelta(minutes = 120) # 2時間前からデータを取得する
    time_min     = time_min.strftime("%Y-%m-%dT%H:%M:00.000000Z")
    access_token = "**********************************************"
    api          = API(access_token = access_token, environment="practice")
    request      = oandapy.InstrumentsCandles(instrument = "USD_JPY", params = { "alignmentTimezone": "Japan", "from": time_min, "count": minutes, "granularity": "M1" })
    api.request(request)

    candle = pandas.DataFrame.from_dict([ row['mid'] for row in request.response['candles'] ])
    candle = candle.set_index([[ row['time'] for row in request.response['candles'] ]])
    print(candle)

実行結果(一部抜粋)
f:id:AdwaysEngineerBlog:20171006113849p:plain

先ほどのスクリプトを実行すると、1時間分のローソク足データをPandasデータフレームに読み込むことができます。 インデックスに時間、カラムoに始値、カラムlに安値、カラムhに高値、カラムcに終値が格納されています。

可視化

データフレームに格納されたデータはmatplotlibを使って可視化することができます。

figure, ax = plt.subplots()
plt_candle( ax, opens = candle.o.values, highs = candle.h.values, lows = candle.l.values, closes = candle.c.values, width=0.4, colorup='#77d879', colordown='#db3f3f')
plt.show()

実行結果 f:id:AdwaysEngineerBlog:20171006113955p:plain

テクニカル指標の計算

テクニカル指標の計算を行います。
今回は、もっとも有名なテクニカル指標の一つであるボリンジャーバンドをプロットします。

ボリンジャーバンドとは
1980年前半にジョン・ボリンジャー氏が公表したテクニカル分析方法です。
移動平均線と、それを中心とした±1σ、±2σ、±3σの7本のラインから成り立っています。
±2σ内でチャートが推移する確率が95.45%なので、それを超えると買われ過ぎ、売られ過ぎといった判断ができます。

シグマの計算式は少し複雑ですが、PandasのSeriesを使うと簡単に計算が可能です。

candlestick.py

avg_move     = pandas.Series.rolling(candle.c, window = 5).mean().dropna().reset_index(drop = True)
sigma        = pandas.Series.rolling(candle.c, window = 5).std(ddof = 0).dropna().reset_index(drop = True)
sigma_plus1  = avg_move + sigma
sigma_plus2  = avg_move + sigma * 2
sigma_plus3  = avg_move + sigma * 3
sigma_minus1 = avg_move - sigma
sigma_minus2 = avg_move - sigma * 2
sigma_minus3 = avg_move - sigma * 3

計算したボリンジャーバンドを先ほどのローソク足チャートに描画すると以下のようになります。

実行結果 f:id:AdwaysEngineerBlog:20171006114039p:plain

一般的には日足で25日平均線などを使用するのが一般的ですが、今回は分足なので分かりやすくするために5分間平均線で計算しています。

まとめ

テクニカル指標の一つであるボリンジャーバンドのプロットをしました。 PythonとPandasを用いると、分析の際に作業の8割を占めると言われている、データの前処理にかかる時間を短縮することができます。
もし興味があればPythonとPandasを使ってみてください。
ありがとうございました。

コードレビューをもっと楽にする

アドテクdivのほったです٩( 'ω' )و
最近はscalaで開発をしています٩( 'ω' )و

(´-`).。oO( もっと楽にコードレビューしたい
(´-`).。oO( 目視でのスタイルのチェックが辛い

と思ったので、静的解析ツールを使ってみようと思います٩( 'ω' )و

Scalastyleを試してみる

ビルドツールはsbtを使っているので、今回はsbtを使ったサンプルです٩( 'ω' )و
公式サイトに手順が記載されているので、
 他のビルドツールを使う場合はそちらを参考にしてください(`・ω・´)ゞ

まずsbt pluginを追加します٩( 'ω' )و

project/plugin.sbt

addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "1.0.0")

次に設定ファイルを用意するためにコマンドを叩きます٩( 'ω' )و

sbt scalastyleGenerateConfig

実行するとカレントディレクトリにxmlファイルが吐き出されると思いますが
これはScalastyleがデフォルトでチェックする設定が書かれています!

早速以下のコードをチェックさせてみます(`・ω・´)ゞ

Hello.scala

package com.example

object Hello {
  def main(args: Array[String]): Unit = {
    println("Hello, world!")
  }
}

コンソールでコマンドを叩くっ٩( 'ω' )و

sbt scalastyle

実行結果が出力されました‹‹(´ω` )/›› ‹‹(  ´)/›› ‹‹( ´ω`)/››

f:id:AdwaysEngineerBlog:20170927120850p:plain

すでにwarningが出てますね(´・ω・`)
デフォルトで設定されている内容は公式ページから確認できるので
今回warningになったものを確認してみます(´-`).。oO

[warn] /Users/hotta_naho/workspace/scala/scalastyle-sample/src/main/scala/com/example/Hello.scala:2: Header does not match expected text
[warn] /Users/hotta_naho/workspace/scala/scalastyle-sample/src/main/scala/com/example/Hello.scala:20:4: Regular expression matched 'println'

それぞれ org.scalastyle.file.HeaderMatchesCheckerorg.scalastyle.file.RegexChecker のチェックでひっかっているようです

scalastyle-config.xmlの該当箇所の設定を確認します٩( 'ω' )و

<check level="warning" class="org.scalastyle.file.HeaderMatchesChecker" enabled="true">
 <parameters>
  <parameter name="header"><![CDATA[// Copyright (C) 2011-2012 the original author or authors.
// See the LICENCE.txt file distributed with this work for additional
// information regarding copyright ownership.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.]]></parameter>
 </parameters>
</check><check level="warning" class="org.scalastyle.file.RegexChecker" enabled="true">
  <parameters>
   <parameter name="regex"><![CDATA[println]]></parameter>
  </parameters>
 </check>

デフォルトの設定だと
HeaderMatchesCheckerはファイルの先頭にLicenseに関する記述が必要そうです(´-`).。oO
また、RegexCheckerは println を使うと引っかかるようです

ではチェックしないようにHello.scalaを修正してみます٩( 'ω' )و

Hello.scala

// Copyright (C) 2011-2012 the original author or authors.
// See the LICENCE.txt file distributed with this work for additional
// information regarding copyright ownership.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.example

object Hello {
  def main(args: Array[String]): Unit = {
    //scalastyle:off
    println("Hello, world!")
  }
}

HeaderMatchesCheckerは単純なファイルの先頭と、
scalastyle-config.xmlで設定しているテキストの比較なので
一言一句同じである必要があります(正規表現も使えます)

また、一部分だけ全てのチェックをさせないようにしたい場合は、
コードの中に scalastyle:off を記述することで、
そのファイルの記述した行以降をチェックしないこともできます٩( 'ω' )و

では再度確認してみます‹‹(´ω` )/›› ‹‹(  ´)/›› ‹‹( ´ω`)/››

f:id:AdwaysEngineerBlog:20170927120929p:plain

全てのチェックが通りました‹‹(´ω` )/›› ‹‹(  ´)/›› ‹‹( ´ω`)/››

やってみて

結構導入が簡単だったのと、コーディングルールをまとめなくてよくなったので
個人的にやってよかったなーと思ってます(灬ºωº灬)

今はデフォルトの設定をチームメンバーと相談して適宜修正していますが 今後も随時メンバーと相談しつつ独自チェックを追加して、
Scalastyleに任せていきたいなーと思います(`・ω・´)ゞ

社内LTやって1年半が経ちました。

こんにちは!入社4年目、 女性 システムエンジニアのはまじですヾ(o´▽`)ノ
半年前からプライベートで動画配信をはじめて、なかなか調子が良さそうなのでそろそろYouTuberになろうかなぁとか思ってたり思ってなかったりする今日この頃です(o´▽`o)

会社では、アプリのサーバーサイドエンジニアとして開発業務を行う傍ら、 開発合宿や社内LT等、開発部署内のイベントの企画・運営も行っております。

今回はその中から開発部署の社内LTについてお話ししようと思います(´∀`*)。・゚+

f:id:AdwaysEngineerBlog:20170922132934j:plain

やることになったきっかけ


以前、1週間に1回知見を共有する会議があったのですが、某テクニカルマネージャーが、

「最近人数が多くなってきて発言しにくい感あるから、会議やめて、定期的にもっと気軽に技術情報を共有出来る場所をつくった方がええ気がしてきたな…。
あ、せっかく大きい会議室空いたし、LTでもやろうぜ。
その方が会議より気軽に話せるし!プレゼンの練習にもなるし!
え、それでええやん、うん、それがえry(ブツブツ…(1人で))」

的なノリで第1回を開催したのがきっかけだそうです。

現在は若手運営メンバーも増え、 情報共有・コミュニケーション・プレゼンの練習を目的に、 “毎月必ず開催する。” ことをルールとして運用しています。 (1回でもやらないとすぐやらなくなっちゃうので。)

内容


テーマ

f:id:AdwaysEngineerBlog:20170922133110p:plain

基本的にはありません。みんなのためになるような話であればOK。
少しマンネリ化してきたときは、開発部署内でテーマを募集して、テーマありでやったりします。

テーマ例

  • 「し○じり先生~俺みたいになるな~」
    • 後輩たちが自分と同じ失敗をしないよう、ベテランの大先輩方から過去の失敗経験を元にありがたい教訓をいただく会です。(これはとても盛り上がりました。)
  • 「Adways0○7『この秋に読んでほしい本』」
    • 自分が読んだ本の中で、是非読んでほしい!という本を紹介し、プレゼンする会です。(来月開催予定)

等々、某テレビ番組から拝借させていただいているネタばかりなのですが、 できるだけキャッチーなテーマにしてみんなが楽しめるようなテーマを日々模索しております。

発表時間

7分 + 質問2、3分。 はじめは5分だったのですが、"情報共有するには5分では足りない"ということで7分に変更しました。 どうしてもたくさん話したい!と言う方にはメイントーク枠もあります。 (発表15分~20分 + 質問5分ぐらい。)

事前準備


  • 発表者を集める
    • 運営担当者が声をかけに行く or 声をかけてもらう
    • やりたいって言いにくいシャイな人もいるかもしれないので、gitlabのissue登録からも応募できるようになっております。

f:id:AdwaysEngineerBlog:20170922133146p:plain

f:id:AdwaysEngineerBlog:20170922133204p:plain

issueが登録されたらslackに通知が飛ぶようにし、登録後すぐに声をかけに行きます。

  • 当日に出す飲み物、お菓子を買う(買いに行くの面倒なのでamazonで購入)
  • ATNDのページを作り観覧者を募る

当日の流れ


会場設営

前説
前説担当の人が台本を考えてきて、発表者が発表しやすいよう、場をあたためるようなとっておきのネタを話します。

発表
見逃してしまった人も見れるように動画撮影します。退勤している人はお酒を飲みながら参加するのも可。

投票+結果発表

投票


発表終了後、会場内にいる人でgoogleアンケートで投票します。得票数が1番多かった人がベストトーク賞 を受賞し、旗が授与されます。

半年に1回、「べすと おぶ べすと決定戦!」という、過去半年間でベストトーク賞を獲得した人の中から、NO.1を決める会もありますヽ(`・ω・´)ゝ

そこでベストトーク賞に輝くとお偉い方々から素敵なプレゼントがもらえたり…!!

発表例


  • CDNについて f:id:AdwaysEngineerBlog:20170922133229j:plain

  • フォントについて語ります f:id:yumi_h_7319_test:20170922103244j:plain

  • 動画編集用プラグイン(Particular)を実際に使ってみた話。 f:id:AdwaysEngineerBlog:20170922133256j:plain

  • 魔法のコード (Ruby大好き久保田君は大体consoleを開いて実演をしています。) f:id:AdwaysEngineerBlog:20170922133313j:plain

  • 海外へカンファレンスに参加したときの情報共有 f:id:AdwaysEngineerBlog:20170922133329j:plain

  • 入社してから学んだこと f:id:AdwaysEngineerBlog:20170922133340j:plain

  • 新年度なのでちょっとエモい話~達人プログラマー第二版より~ f:id:AdwaysEngineerBlog:20170922133350j:plain

等々、業務で学んだことから自分が興味のあることまで、 思い思いの発表方法でプレゼンをします(●ノ▽`)ノ

やってよかったこと


  • 入社前に学んだことを知ることができる。
    • 前の職場ではこんなことしてた、大学でこんな研究してた、等。
  • 発表の準備をキッカケに勉強する
  • アピールの場にもなる
    • 得意なこと、こんなこと勉強してます、等。
  • 仕事で関わらない人とも会話するキッカケができる。
  • 自分が行けなかったカンファレンスの話しを聞くことができる
  • 他の部署がどんなことをしているのかわかる

今後改善したいこと


  • 盛り上がってる感が出にくい
    • みんなちょいちょいリアクションするけど、控えめで盛り上がってる感が出にくいので、もっとリアクションしやすい環境をつくりたい(改善策実施中)
  • 発表者の固定化
    • バラけるようにはしているけど、発表者が固定化されてきているので、もっといろんな人が発表しやすいような環境をつくりたい

社内LTをする際の参考に少しでもなればなと思います。 改善策をを試した結果はいつか当ブログの編集者である奥村君が投稿してくれると思います。 ではでは(o´ω`o)♪

VagrantとAnsibleでScalaの環境構築

こんにちは!入社2年目、広告サービスチームの山﨑です!
この頃ダイエット食品試しまくって5kg痩せました!!!毎日がリバウンドの恐怖&食欲との戦いです!☆
そんな私は業務ではずっとPerl を使って開発をしていたのですが、今後Scalaを導入していくということで環境構築を行いました。
実際は手動で行ったのですが、VagrantとAnsibleを使ったことがなかったのでこの二つを使ってもう一つ環境を作ってみました!

環境

ansible実行ホスト

  • CentOS7.3
  • Ansible 2.3.2.0

セットアップ対象

  • CentOS7.3

仕事で使用しているPCがWindowsでAnsibleを簡単に実行できないのでLinuxの仮想マシンを2つ用意しました。

VagrantでCentOS7 インストール

$ mkdir centos

Vagrantfileを作成
$ vagrant init CentOS7/

ネットワーク、共有フォルダ設定を追記
$ vim Vagrantfile

Vagrant.configure("2") do |config|
  config.vm.box = "centos/7"
  config.vm.network :private_network, ip: "192.168.33.10" #任意のip
  config.vm.synced_folder ".", "/vagrant", type: "virtualbox" 
end

$ vagrant up

$ vagrant ssh

Windows環境だとrsyncが見つからないよとエラーがでたので
config.vm.synced_folder ".", "/vagrant", type: "virtualbox"
を追記しました。
Windowsのコマンドプロンプトではsshログインできないので、ssh接続できるツールを使用してください。今回は同期におすすめされたGit Bashを使っています!

これでCentOSのインストールは完了です!

Ansible

今回作成したplaybookがこちら!

- hosts: all
  become: yes
  tasks:
    - name: install common package
      yum: name={{ item }}
      with_items:
        - unzip
        - wget

    - name: download JDK
      get_url:
        url: http://download.oracle.com/otn-pub/java/jdk/8u144-b01/090f390dda5b47b9b721c7dfaa008135/jdk-8u144-linux-x64.rpm
        headers: "Cookie:oraclelicense=accept-securebackup-cookie"
        dest: /home/vagrant/jdk-8u144-linux-x64.rpm

    - name: import rpm
      yum:
        name: /home/vagrant/jdk-8u144-linux-x64.rpm
        state: present

    - name: get Scala
      get_url:
        url: http://downloads.typesafe.com/scala/2.11.7/scala-2.11.7.tgz
        dest: /home/vagrant/

    - name: unarchive scala.tgz
      unarchive:
        src: /home/vagrant/scala-2.11.7.tgz
        dest: /home/vagrant
        remote_src: True

    - name: scala path
      become: False
      lineinfile:
        path: /home/vagrant/.bash_profile
        regexp: 'export PATH%'
        insertbefore: 'export PATH'
        line: 'export PATH=$PATH:/home/vagrant/scala-2.11.7/bin'

実行!

$ ansible-playbook -i hosts main.yml

完了してscalaコマンドを打つと、scalaconcoleが立ち上がるはずです!!
ではではそのまんまって感じなのですが実行内容を解説させて頂きます!

install common package

必要なパッケージをインストール

download JDK & import rpm

scalaを動かすのに必要なJDKのダウンロードです。サイトを見ていただくと分かるのですが、ラジオボタンでライセンス認証を行わなければなりません。 CUIから行うにはCookieのオプションをつけてあげればダウンロードできます!

get Scala & unarchive scala.tgz

Scalaのインストール。バージョンは適宜選択してください。 任意のパスに解凍します。

scala path

パスを通す為に.bash_profileに scala.taz を解凍したパスを追記します。

まとめ

本当はActivatorやIntelliJをインストールするところまでいきたかったのですが・・・今後の展望と致します。
途中エラーがでまくったりしてましたが、Ansibleを実行して全部のtaskが上手くいくととっても気持ちよいですね!
最後まで読んで頂きありがとうございました!

jsxでデザイナー向けにphotoshopデータのチェッカーを作った

こんにちは、相原です。

自分がデザイナー出身ということもあり、
どうにかデザイナーの作業を効率化出来ないかと考え、チェッカーを作ってみました。

photoshopでデザインを作り込んでいるとレイヤー数が増え、
また不要なレイヤーを消し忘れて非表示にしたまま放置している人が多いかと思います。
そんな時に自動で非表示のレイヤーを探し、確認あるいは削除してくれるチェッカーです。

JSXとは

JavaScriptでPhotoshopを制御するファイルのことを「JSX」といいます。
昔からPhotoshopに搭載されていて、機能追加や自動化をすることが出来ます。

チェッカーの主な機能

非表示のまま放置しているレイヤーがあるとします。
レイヤー
f:id:AdwaysEngineerBlog:20170907153755p:plain

(いるレイヤーまで1個非表示になっちゃってますね)

ファイル > スクリプト > 参照 でチェッカーのjsxファイルを読み込みます。
読み込み
f:id:AdwaysEngineerBlog:20170907153811p:plain

するとチェックが始まり、アラートが表示されます。
削除対象
f:id:AdwaysEngineerBlog:20170907153833p:plain

削除方法
f:id:AdwaysEngineerBlog:20170907153847p:plain

■手動で削除
そのまま終了するか、対象のレイヤーに黄色のカラーラベルをつけるか選択できます。
画像はカラーラベルをつけたものです。
これでどのレイヤーが削除対象か分かり易いですね。
ラベル付き
f:id:AdwaysEngineerBlog:20170907154637p:plain

■1つずつ確認
非表示のレイヤー1つずつアラートで確認し、削除したいものだけ「はい」を押すと削除されます。
削除確認
f:id:AdwaysEngineerBlog:20170907154648p:plain

■一括削除
非表示のレイヤーは自動ですべて削除されます。

コード

カラーラベルの付け方はこちらのサイトを参考にしています。

var document;
var targetCnt = 0; // 削除対象のレイヤーを数える変数
var howToDeleteFlg; // 0=手動, 1=確認, 2=一括

function start(){
  alert('チェックを開始します。');
  document = app.activeDocument;
  searchLayer(document.layers);
  if(targetCnt == 0){
    alert('削除対象のレイヤーがないので終了します。');
    return; // 削除対象がなければ終了する
  }
  howToDelete(document.layers);
  alert('チェックを終了します。');
}

// 非表示レイヤーの検索 -------------------->
function searchLayer(obj){
  var i;
  switch(obj.typename){
    case "Layers":
      var visiblities = [];
      for(i = obj.length - 1; i >= 0; i--){
        var rep = searchLayer(obj[i]);
        if(rep == false) targetCnt++;
      }
      break;
    case "LayerSet":
      if(!obj.visible){
        processingBranch(obj);
        return false;
      }
      for(i = obj.layers.length - 1; i >= 0; i-- ){
        var rep = searchLayer(obj.layers[i]);
        if(rep == false) targetCnt++;
      }
      break;
    default:
      if(!obj.visible){
        processingBranch(obj);
        return false;
      }
      break;
  }
}

// 削除方法選択用のダイアログ -------------------->
function howToDelete(obj){
  alert('削除対象のレイヤーが' + targetCnt + '個あります。');
  deleteWin = new Window("dialog", "削除方法を選択してください。");
  manualBtn = deleteWin.add("button", { width: 150, height: 25, x: 25, y: 25 }, "手動で削除");
  confirmationBtn = deleteWin.add("button", { width: 150, height: 25, x: 115, y: 25 }, "1つずつ確認");
  bulkBtn = deleteWin.add("button", { width: 150, height: 25, x: 205, y: 25 }, "一括削除");
  manualBtn.onClick = function(){
    howToDeleteFlg = 0;
    deleteWin.close();
    var result = confirm('カラーラベル(黄色)で印をつけますか?');
    if(result) searchLayer(obj); // カラーラベルをつける処理へ
  }
  confirmationBtn.onClick = function(){
    // 1つずつ確認する処理へ移動
    howToDeleteFlg = 1;
    deleteWin.close();
    searchLayer(obj);
  }
  bulkBtn.onClick = function(){
    var result = confirm('本当に一括削除してよろしいですか?');
    if(result){
      // 一括削除する処理へ移動
      howToDeleteFlg = 2;
      deleteWin.close();
      searchLayer(obj);
    }
  }
  deleteWin.show();
}

// 削除方法が手動、確認、一括かによって処理の分岐 -------------------->
function processingBranch(obj){
  if(howToDeleteFlg == 0){
    app.activeDocument.activeLayer = obj;
    var util = new PSLayerUtil();
    util.setLayerColor(PSLayerUtil.LayerColors.None);
    util.setLayerColor(PSLayerUtil.LayerColors.Yellow);
    return false;
  }else if(howToDeleteFlg == 1){
    confirmationDelete(obj);
    return false;
  }else if(howToDeleteFlg == 2){
    obj.remove();
    return false;
  }else{
    return false;
  }
}

// レイヤーの選択 -------------------->
function selectLayer(obj){
  app.activeDocument.activeLayer = obj;
  obj.visible = false;
}

// カラーラベル設定 -------------------->
var PSLayerUtil = function(){
  this._colorRef = new ActionReference();
  this._colorRef.putEnumerated(charIDToTypeID('Lyr '), charIDToTypeID('Ordn'), charIDToTypeID('Trgt'));
}
PSLayerUtil.LayerColors = {
  Yellow: 'Ylw ',
  None: 'None'
};
PSLayerUtil.prototype = {
  _colorRef: null,
  setLayerColor: function(layerColor) {
    var colorDescriptor = new ActionDescriptor();
    colorDescriptor.putEnumerated(charIDToTypeID('Clr '), charIDToTypeID('Clr '), charIDToTypeID(layerColor));
    var desc = new ActionDescriptor();
    desc.putReference(charIDToTypeID('null'), this._colorRef);
    desc.putObject(charIDToTypeID('T   '), charIDToTypeID('Lyr '), colorDescriptor);
    executeAction(charIDToTypeID('setd'), desc, DialogModes.NO);
    return this.layerColor();
  },
  layerColor: function() {
    var desc = executeActionGet(this._colorRef);
    var charID = typeIDToCharID(desc.getEnumerationValue(charIDToTypeID('Clr ')));
    for(var key in PSLayerUtil.LayerColors) {
      var value = PSLayerUtil.LayerColors[key];
      if(value === charID) return key;
    }
    return 'None';
  },
}

// 削除方法が1つずつ確認する場合のダイアログ -------------------->
function confirmationDelete(obj){
  selectLayer(obj);
  var result = confirm('削除対象【' + obj.name + '】を削除しますか?');
  if(result){
    obj.remove();
  }
}
start();

さいごに

jsxは少し特殊な書き方もしますが、簡単に自動化出来るので活用していけそうです。
このチェッカーも2時間半ほどで作れました。
今後もデザイナーの作業を効率化出来るようなものを作ってみたいと思います╰(✿´⌣`✿)╯