状況
昨日は、High-loバイナリーのエントリー部分を完成しました。
適当にGithubから、コードを頂きました。
苦労したこと
- セレニウムを全く知らないこと(やばめの金属化合物かと思いました。。。)
- XPATHの取り方が、まったく分かりませんでした。。。
結果
-
BOPのバックテストでは5分足エントリで勝率60%
→ 実際のトレードでは、この閾値では、ほとんどサインが出なかった。 -
サインの閾値範囲を、緩めてエントリーしたら、かなりの勝率で利益が取れた。
→ 調子に乗って、実弾10000円をエントリーして、夜中に持ち越ししたら、残高が0円になった。
反省点
- BOPで勝負をかけるのは、まだ早すぎる → signalと勝率についてのデータ収集を行い、統計的有意差を検証すること
- MT4については、1分足では危険すぎる → 1分、5分、15分のマルチタイムフレームの戦略を立てる必要がある
ソース
一応、今回のソースを以下に示します。
(なんやかんや言うて、mlopsぽいことができるスキルがついてきました。)
main.py
from datetime import datetime
from selenium import webdriver
from selenium.webdriver.chrome import service as fs
import chromedriver_binary
from selenium.webdriver.common.by import By
BC_ADRESS = "Mail or Wallet"
PASSWORD = "PASSWORD"
def l(str):
print("%s : %s"%(datetime.now().strftime("%Y/%m/%d %H:%M:%S"),str), flush=True)
def s(t = 5):
import time
time.sleep(t)
def x(str = ""):
import traceback
traceback.print_exc()
if str != "":
l(str)
def start():
# ドライバー指定でChromeブラウザを開く
chrome_service = fs.Service(executable_path='./chromedriver')
b = webdriver.Chrome(service=chrome_service)
b.get('https://app.highlow.com/quick-demo?source=header-quick-demo-cta')
s()
return b
def login():
b.find_element_by_css_selector('.login_menu_button a').click()
i = b.find_element_by_id('login_form_btc_address')
i.send_keys(BC_ADRESS)
i = b.find_element_by_id('login_form_password')
i.send_keys(PASSWORD)
b.find_element_by_id('login_button').click()
s()
def purchase(driver, high_low_xxx, entry_price):
if high_low_xxx == "high":
b.find_element(by=By.XPATH,value = "//div[text()='High']").click()
s(0.5)
b.find_element(by=By.XPATH,value = "//div[text()='今すぐ購入']").click()
s(0.5)
b.find_element(by=By.XPATH,value = "//div[text()='High']").click()
elif high_low_xxx == "low":
b.find_element(by=By.XPATH,value = "//div[text()='Low']").click()
s(0.5)
b.find_element(by=By.XPATH,value = "//div[text()='今すぐ購入']").click()
s(0.5)
b.find_element(by=By.XPATH,value = "//div[text()='Low']").click()
@app.get("/order/")
async def order(signal : float ,db:Session = Depends(get_db)):
if signal>2 and signal<100:
s(0.5)
purchase(b,"high",1000)
s(0.5)
elif signal>0.001 and signal<0.5:
s(0.5)
purchase(b,"low",1000)
s(0.5)
return {"ordered":str(signal)}
MT4
main.c
#property copyright "Copyright 2016, gogojungle"
#property version "1.00"
#property strict
string URL = "http://127.0.0.1/";
datetime mBeforeBarCreationDateTime;
#define SIGNAL_NONE 0
#define SIGNAL_BUY 1
#define SIGNAL_SELL 2
#define SIGNAL_CLOSEBUY 3
#define SIGNAL_CLOSESELL 4
#property copyright "Expert Advisor Builder"
#property link "http://sufx.core.t3-ism.net/ExpertAdvisorBuilder/"
extern int MagicNumber = 20170302;
extern bool EachTickMode = False;
extern double Lots = 0.1;
extern double LotMultiple = 1.2; //ナンピンロット係数
//ポジション
extern int Slippage = 3;
extern bool Use_limitorder = True;
extern bool Use_stoporder = True;
extern bool UseT_S = True;
extern bool UseT_L = True;
extern bool Use_close = True;
extern bool UseDuration = True; //
extern int expiration = 200; //エントリー有効時間
extern int maxDuration = 200; //ポジション保有時間
//---- input parameters
extern string param1 = "Current time frame";
extern int nATR = 20;
extern double Coef = 2.0;
extern double margin = 0.0001;
extern int nLS_MA = 10;
extern int atrLS =1;
extern int space = 100; //ナンピン幅(ピプス)
extern int multi = 1;
//---- input parameters
extern int nPeriod_RSI = 14;
extern int nPeriod_RSI2 = 28;
extern int nPeriod_MA = 25;
extern int MA_Method = 0;
extern int min_gap = 2;
extern int TIMERAG = 3;
extern int TIMERAG2 = 3;
extern double PROF = 500;
int Limit = 200;
int nLine = 2;
int BarCount;
int Current;
bool TickCheck = False;
bool close_mode_buy;
bool close_mode_sell;
datetime entryTime = 0; // エントリー時間
datetime bartime = 0;
int OnInit()
{
Init();
return(INIT_SUCCEEDED);
};
int Init(){
string res,filename,sep_str[];
datetime m1,m5,m15,current;
int pos;
res = GET(URL + "getlasttime/", "");
pos =StringSplit(res,'\"',sep_str);
Print("pos ",pos);
if(pos!=0)
{
m1 = StringToTime(sep_str[3]);
m5 = StringToTime(sep_str[7]);
m15 = StringToTime(sep_str[11]);
}
SendValue(PERIOD_M1,"forex_m1",m1);
SendValue(PERIOD_M5,"forex_m5",m5);
SendValue(PERIOD_M15,"forex_m15",m15);
return(INIT_SUCCEEDED);
}
void SendValue(string peristr,string forex, datetime end){
for(int i=0; i<100000; i++){
if (end > iTime(NULL,peristr,i))
break;
string data = TimeToString(iTime(NULL,peristr,i))
+","+ forex + "," + DoubleToString(iClose(NULL,peristr,i));
Print(data);
POST(URL + "gettick/", data);
}
}
//! @brief ティック毎の処理
void OnTick()
{
// 最新の1分足のバーの形成開始時刻を取得。
datetime current = iTime(NULL, PERIOD_M1, 0);
// 前のティックでの形成開始時刻と比較。
if (current != mBeforeBarCreationDateTime)
{
// 違うならば前のバーが確定し新しいバーになった=1分毎の更新タイミング。
On1Minute();
// バーの形成開始時刻を更新。
mBeforeBarCreationDateTime = current;
}
};
bool POST(string url, string text){
string headers;
string data;
char post[],result[];
headers = "Content-Type: application/json\r\n";
StringReplace(text, "\n", "\\n");
data = "{\"content\":\""+text+"\"}";
ArrayResize(post,StringToCharArray(data,post,0,WHOLE_ARRAY,CP_UTF8)-1);
int res=WebRequest("POST",url,headers,5000,post,result,headers);
if(res == -1){
Print(__FUNCTION__ + " Error code =",GetLastError(),data);
return(false);
}
Print("POST success! ", CharArrayToString(result, 0, -1));
return(true);
}
string GET(string url, string text){
string headers;
string data,str;
char post[],result[];
headers = "Content-Type: application/json\r\n";
StringReplace(text, "\n", "\\n");
data = "{\"content\":\""+text+"\"}";
ArrayResize(post,StringToCharArray(data,post,0,WHOLE_ARRAY,CP_UTF8)-1);
int res=WebRequest("GET",url,headers,5000,post,result,headers);
if(res == -1){
Print(__FUNCTION__ + " Error code =",GetLastError(),data);
return(false);
}
//--- Receive a link to the image uploaded to the server
str=CharArrayToString(result);
return(str);
}
int On1Minute()
{
int Order = SIGNAL_NONE;
int total, Ticket;
bool ret = false;
double buy_price[100];
double sell_price[100];
int i;
string res,str,pos,filename,sep_str[];
//+------------------------------------------------------------------+
//| Variable Begin |
//+----
//------------------------------------------------------------+
//Check position
bool IsTrade = False;
total = OrdersTotal();
// if(total>10)
// IsTrade = True;
double signal;
HideTestIndicators(false);
Print("On1Minute");
Init();
Print("predict", GET(URL + "predict/", ""));
Print("predict1", GET(URL + "predict1/", ""));
res = GET(URL + "predict2/", "");
Print("signal is " + res);
pos = GET(URL + "order/" + "?signal=" + res,"");
signal = (float)res;
if (signal>2 && signal<100) {
Order = SIGNAL_BUY;
}
if (signal>0.001 && signal<0.5) {
Order = SIGNAL_SELL;
}
static int BarsBefore = 0;
int BarsN = Bars;
int BarsCheck = BarsN - BarsBefore;
//Buy
if ( Order == SIGNAL_BUY && ((EachTickMode && !TickCheck) || (!EachTickMode && (Bars != BarCount))))
{
if (!IsTrade)
{
//Check free margin
if (AccountFreeMargin() < (1000 * Lots))
{
Print("We have no money. Free Margin = ", AccountFreeMargin());
return (0);
}
if (Use_limitorder)
{
for (i = 0; i < multi; i++)
{
Ticket = OrderSend(Symbol(), OP_SELLLIMIT, (i * LotMultiple + 1) * Lots, NormalizeDouble(Bid - i * space * iStdDev(NULL, 0, nPeriod_MA, 0, MODE_EMA, PRICE_CLOSE, 0) * 0.01, Digits), Slippage, 0, 0, "Buy(#" + Symbol() + Period() + ")", MagicNumber, TimeCurrent() + expiration * Period() * 60, DodgerBlue);
if (Ticket > 0)
{
if (OrderSelect(Ticket, SELECT_BY_TICKET, MODE_TRADES))
{
Print("BUY limit order opened : ", OrderOpenPrice());
}
else
{
Print("Error opening BUY limit order : ", GetLastError());
}
}
}
if (EachTickMode)
TickCheck = True;
if (!EachTickMode)
BarCount = Bars;
return (0);
}
}
}
//Sell
if ( Order == SIGNAL_SELL && ((EachTickMode && !TickCheck) || (!EachTickMode && (Bars != BarCount))))
{
if (!IsTrade)
{
//Check free margin
if (AccountFreeMargin() < (1000 * Lots))
{
Print("We have no money. Free Margin = ", AccountFreeMargin());
return (0);
}
if (Use_limitorder)
{
for (i = 0;i < multi; i++)
{
Ticket = OrderSend(Symbol(), OP_BUYLIMIT, (i * LotMultiple + 1) * Lots, NormalizeDouble(Ask + i * space * iStdDev(NULL, 0, nPeriod_MA, 0, MODE_EMA, PRICE_CLOSE, 0) * 0.01, Digits), Slippage, 0, 0, "Sell(#" + Symbol() + Period() + ")", MagicNumber, TimeCurrent() + expiration * Period() * 60, DeepPink);
if (Ticket > 0)
{
if (OrderSelect(Ticket, SELECT_BY_TICKET, MODE_TRADES))
{
Print("SELL limit order opened : ", OrderOpenPrice());
}
else
{
Print("Error opening SELL limit order : ", GetLastError());
}
}
}
if (EachTickMode)
TickCheck = True;
if (!EachTickMode)
BarCount = Bars;
return (0);
}
}
}
if (EachTickMode)
TickCheck = True;
if (!EachTickMode)
BarCount = Bars;
return (0);
}
//+------------------------------------------------------------------+
bool CloseAll(int type)
{
Print("Close All");
for (int i = OrdersTotal() - 1; i >= 0; i--)
{
if (!OrderSelect(i, SELECT_BY_POS))
continue;
if (OrderSymbol() != Symbol())
continue;
if (OrderMagicNumber() != MagicNumber)
continue;
if (OrderType() != type)
continue;
if (!OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), Slippage))
{
Print("Close Error");
return (false);
}
}
return (true);
}
bool CloseAll_maxDuration(int type)
{
for (int i = OrdersTotal() - 1; i >= 0; i--)
{
if (!OrderSelect(i, SELECT_BY_POS))
continue;
if (OrderSymbol() != Symbol())
continue;
if (OrderMagicNumber() != MagicNumber)
continue;
if (OrderType() != type)
continue;
if (OrderType() != type)
continue;
if (int(TimeCurrent() - OrderOpenTime()) < maxDuration * Period() * 60)
continue;
if (StringFind(OrderComment(), Period(), 0) == false)
continue;
if (!OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), Slippage))
{
Print("Close Error");
return (false);
}
else{
Print("Close All maxDuration");
return (true);
}
}
return(true);
}
double AdjustPoint()
{
//提示レートの小数点桁数を取得する
int disit = (int)MarketInfo(NULL, MODE_DIGITS);
//2桁と3桁は2桁に統一する
if (disit == 2 || disit == 3)
{
return 0.01;
}
//4桁と5桁は4桁に統一する
if (disit == 4 || disit == 5)
{
return 0.0001;
}
//2~5桁以外の桁が発生した場合は、0を返す。
return 0;
}