Pythonista3で、計算結果とグラフを表示するアプリを作ってみた

Pythonista3

Pythonista3を使って、GUIで値を入力し、計算結果とグラフを表示するアプリを作ってみました。

全体構成

構成は下記2つのブロックで構成されています

  • ボタンタップ時の動作定義
  • GUIの各部品作成~配置

コード説明

ボタンタップ時の動作定義部

def fx_margin_calc(sender):
  mmr      = float(mmr_i.text)/100
  lot_u    = float(lot_u_i.text)

ボタンタップ時の動作をdefで定義します。引数は、必ずsenderとします。これにより、Acationの指定元であるオブジェクトが渡されます。2行目以降、GUIから入力されたデータを参照し各変数に格納していきます。GUIから入力されるデータは文字列(String)であるため、floatを使い小数に型変換しておきます。

  margin -= spread
  margin  = int(margin)
  
  c_l2.text = str(margin)

GUIから読みだしたデータから計算した結果をGUIに返します。
表示する先のデータは文字列である必要があるため、今度はstrで文字列に変換して「c_l2.text」に格納しています。

  plt.clf()
  ~省略~
  plt.legend()
  
  with io.BytesIO() as buf:
    plt.savefig(buf)
    png = ui.Image.from_data(buf.getvalue())
    img_i.image = png

グラフはmatplotlibを使って作ります。作ったグラフは、ui.Image型に変換しないとui.view上で表示させることができないため、ByteIOを使うことで、bufに一旦取り出し、ui.Image.from_dataを使って、ui.Image型に変化しています。

GUIの各部品作成~配置

# UIの作成
v = ui.View()
v.background_color = '#e2e2e2' 

# 計算条件入力
mmr_l      = ui.Label(frame=(10,  10, 200, 30), alignment=2, text='証拠金維持率[%]')

泥臭い書き方ですが、部品を一つずつ作って、frameで配置座標を指定しながら作っていっています。
描いている内容は繰り返しなので、これ以降は省略します。
LabelとTextFildeの繰り返しで入力部分を作っているので、1つのデータ入力分をクラス化してみるともっとスマートに書けたかもしれません。この辺の書き方はまた調べて紹介したいと思います。

まとめ

GUIで値を入力し、計算結果とグラフを表示するアプリを作ってみました。頻繁に計算するような場合楽になると思いますので、是非試してみてください。
※FXは素人です、コード中の算出式は保証できません。アプリの作り方として参照ください。

コード例

import io
import matplotlib.pyplot as plt
import numpy as np
import ui

def fx_margin_calc(sender):
  mmr      = float(mmr_i.text)/100
  lot_u    = float(lot_u_i.text)
  pips     = float(pips_i.text)
  spread   = float(spread_i.text)
  leverage = float(leverage_i.text)
  balance  = float(balance_i.text)
  lot      = float(lot_i.text)
  bid      = float(bid_i.text)

  margin  = balance/lot/lot_u/pips
  margin -= bid/leverage*mmr/pips
  margin -= spread
  margin  = int(margin)
  
  c_l2.text = str(margin)
  
  x = np.arange(bid*0.99, bid*1.01, bid*0.0002)
  a  = x+balance/lot/lot_u-x/leverage*mmr
  a -= spread*pips
  b  = x-balance/lot/lot_u+x/leverage*mmr
  b += spread*pips

  plt.clf()
  plt.plot(x, b, color='red', label='bid')
  plt.plot(x, a, color='blue', label='ask')
  plt.title('margin')
  plt.xlabel('position value')
  plt.ylabel('margin')
  plt.grid() 
  plt.legend()
  
  with io.BytesIO() as buf:
    plt.savefig(buf)
    png = ui.Image.from_data(buf.getvalue())
    img_i.image = png
  
# UIの作成
v = ui.View()
v.background_color = '#e2e2e2' 

# 計算条件入力
mmr_l      = ui.Label(frame=(10,  10, 200, 30), alignment=2, text='証拠金維持率[%]')
lot_u_l    = ui.Label(frame=(10,  40, 200, 30), alignment=2, text='1Lot当たりの通貨量')
pips_l     = ui.Label(frame=(10,  70, 200, 30), alignment=2, text='1pips')
spread_l   = ui.Label(frame=(10, 100, 200, 30), alignment=2, text='スプレッド')
leverage_l = ui.Label(frame=(10, 130, 200, 30), alignment=2, text='レバレッジ')
balance_l  = ui.Label(frame=(10, 160, 200, 30), alignment=2, text='残高')
lot_l      = ui.Label(frame=(10, 190, 200, 30), alignment=2, text='ポジション保有Lot')
bid_l      = ui.Label(frame=(10, 220, 200, 30), alignment=2, text='ポジション保有時のbid')

mmr_i      = ui.TextField(frame=(220,  10, 100, 30), placeholder='100')
lot_u_i    = ui.TextField(frame=(220,  40, 100, 30), placeholder='100000')
pips_i     = ui.TextField(frame=(220,  70, 100, 30), placeholder='0.01')
spread_i   = ui.TextField(frame=(220, 100, 100, 30), placeholder='1.2')
leverage_i = ui.TextField(frame=(220, 130, 100, 30), placeholder='1000')
balance_i  = ui.TextField(frame=(220, 160, 100, 30), placeholder='10000')
lot_i      = ui.TextField(frame=(220, 190, 100, 30), placeholder='0.01')
bid_i      = ui.TextField(frame=(220, 220, 100, 30), placeholder='150')
mmr_i.text='100'
lot_u_i.text='100000'
pips_i.text='0.01'
spread_i.text='1.2'
leverage_i.text='1000'
balance_i.text='10000'
lot_i.text='0.01'
bid_i.text='150'
mmr_i.keyboard_type = ui.KEYBOARD_NUMBERS
lot_u_i.keyboard_type = ui.KEYBOARD_NUMBERS
pips_i.keyboard_type = ui.KEYBOARD_NUMBERS
spread_i.keyboard_type = ui.KEYBOARD_NUMBERS
leverage_i.keyboard_type = ui.KEYBOARD_NUMBERS
balance_i.keyboard_type = ui.KEYBOARD_NUMBERS
lot_i.keyboard_type = ui.KEYBOARD_NUMBERS
bid_i.keyboard_type = ui.KEYBOARD_NUMBERS

# 計算結果表示
c_l1 = ui.Label(frame=(10, 280, 200, 30), alignment=2, text='許容変動[pips]')
c_l2 = ui.Label(frame=(220, 280, 100, 30))
c_b = ui.Button(frame=(330, 280, 40, 30), title='計算')
c_b.action = fx_margin_calc
img_i = ui.ImageView(frame=(10, 320, 350, 300))

v.add_subview(mmr_l)
v.add_subview(lot_u_l)
v.add_subview(pips_l)
v.add_subview(spread_l)
v.add_subview(leverage_l)
v.add_subview(balance_l)
v.add_subview(lot_l)
v.add_subview(bid_l)
v.add_subview(mmr_i)
v.add_subview(lot_u_i)
v.add_subview(pips_i)
v.add_subview(spread_i)
v.add_subview(leverage_i)
v.add_subview(balance_i)
v.add_subview(lot_i)
v.add_subview(bid_i)
v.add_subview(c_l1)
v.add_subview(c_l2)
v.add_subview(c_b)
v.add_subview(img_i)

# アプリを表示
v.present(style='sheet')
タイトルとURLをコピーしました