/// <summary> /// 取引履歴をスプレッドシートへ送信する /// </summary> /// <param name="bhc">送信するメッセージコンテナ 1つ</param> public static String PostBoResult(BoHistroyContainer bhc) { string ret = string.Empty; try { // 送信待ちでないものは終了 そのまま返す if (bhc.State != HistoryState.hsWaitPost) { return(bhc.PostResultData); } SignalResult boResultSig = bhc.ResultSig; SignalOrder boEntrySig = bhc.Sig; // 送信用パラメータ文字列作成 string postResultParam = string.Empty; postResultParam += "result=" + boResultSig.R_Result; // 結果 postResultParam += "&pair=" + boResultSig.R_TradeBrand; // 通貨ペア postResultParam += "&rate=" + boResultSig.R_BidRate; // 入札レート postResultParam += "&bidTime=" + boResultSig.R_BidTime; // 入札時間 postResultParam += "&judgeTime=" + boResultSig.R_JudgeTime; // 判定時間 postResultParam += "&state=Done"; // + boResultSig.R_State; // ステータス Done固定 postResultParam += "&judgeRate=" + boResultSig.R_JudgeRate; // 判定レート postResultParam += "&bidPrice=" + boResultSig.R_BidPrice.Replace("¥", ""); // 入札金額 postResultParam += "&payout=" + boResultSig.R_PayOut.Replace("¥", ""); // ペイアウト postResultParam += "&signalName=" + bhc.Sig.signalRoomName; // シグナル名 postResultParam += "&environment=" + bhc.Sig.getEnviromentNames(); // 環境の送信 postResultParam += "&conditionPrice=" + boEntrySig.bidPrice; // エントリー時の判断した時のレート価格 // 部屋名のコンバート postResultParam += "&SignalName=DATA"; //送信用コマンドを保持 ret = bhc.PostURL_SpredSheet + postResultParam; Process cmd = new Process(); cmd.StartInfo.FileName = "PowerShell.exe"; cmd.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; //PowerShellのWindowを立ち上げずに実行。 cmd.StartInfo.Arguments = @"curl '" + bhc.PostURL_SpredSheet + postResultParam + "'"; // 引数optionsをShellのコマンドとして渡す。 cmd.Start(); cmd.Close(); return(ret); } catch (Exception e) { DebugPrint(e, "postBoResult"); bhc.PostResultData = string.Empty; return(ret); } }
/// <summary> /// エントリーする時間が高い重要度の時間帯でないかどうかチェックする /// 重要度前後30分以内であればスルーする /// </summary> /// <returns>True 高い重要度 / False それ以外の重要度または重要でない</returns> public bool JudgeEnvironmentSignalZone(ref SignalOrder sig, ref LINEControl cLine) { bool ret = false; //// 指定時間帯の時トレードを通す //DateTime dudgeTime = sig.tradeEntryTime.AddMinutes(5); //// 指定の時間帯であれば取引を行う //if ( DateTime.Parse("11:00") <= dudgeTime && dudgeTime < DateTime.Parse("12:00") ) //{ // ret = false; //} else //{ // ret = true; //} // TODO:今は無条件でテスト sig.Environment = EnvState.esTest; return(ret); //TODO:必要になったらコメントを外す // IsCheckImportanceTimeZone //try //{ // foreach (invCalender inv in EconomicList) // { // DateTime sTime = inv.evTime.AddMinutes(-30); // DateTime eTime = inv.evTime.AddMinutes(30); // // 間に入っているか? // if (sTime <= sig.tradeEntryTime && sig.tradeEntryTime <= eTime) // { // ret = true; // // 回避になった場合メッセージを送る // cLine.putSignalMsgToRoom(Constants.ROOM_NAME_CmdLine // , sig.signalRoomName // , "次の経済指標に引っかかった為エントリーしませんでした。" // + "経済指標 【 "+ inv.evTime.ToString("HH:mm:ss") + " " + inv.detail + " 】 " // + "シグナル【" + sig.rawOriginalMessage + "】" ); // break; // 一つでも見つかったら終了 // } // } //} //catch (Exception e) //{ // CommonControl.DebugPrint(e, "経済指標 時間比較失敗"); //} //return ret; }
/// <summary> /// 平文のシグナル文章を各パラメータに解析する /// </summary> /// <param name="roomName">受けた部屋名</param> /// <param name="argSignalFlatWord">何れかのシグナル文章</param> /// <returns></returns> public static SignalOrder AnalysisWord(string roomName, string argSignalFlatWord) { SignalOrder ret = new SignalOrder(); try { switch (roomName) { case Constants.ROOM_NAME_AUXESIS: // AUXESIS用 ret = AnalysisByAuxesisMsg(argSignalFlatWord); break; case Constants.ROOM_NAME_RISE: // RISE用未作成 //ret = new SignalOrder(); break; case Constants.ROOM_NAME_CmdLine: case Constants.ROOM_NAME_SignalMeijin: ret = AnalysisBySignalMeijin(argSignalFlatWord); break; case Constants.ROOM_NAME_MIYU: ret = AnalysisByMiyuMsg(argSignalFlatWord); break; case Constants.ROOM_NAME_DebugRoomName: //debug用 ret = AnalysisByAuxesisMsg(argSignalFlatWord); break; } } catch (Exception e) { // シグナル解析に失敗した // throwしない CommonControl.DebugPrint(e); } finally { // 終わった後に格納 ret.signalRoomName = roomName; // 部屋名 ret.rawOriginalMessage = argSignalFlatWord; // メッセージ原文 } return(ret); }
/// <summary> /// メッセージ /// デバッグ用 /// </summary> public static void ForDebugOnly() { Constants.Initialize(); try { //CommonControl.OutPutTextBoResult("ABC" + Environment.NewLine + " @ " + Environment.NewLine + "D E F G H I J K "); string str = ""; str = str + ""; SignalOrder sio = HighLowControl.AnalysisWord(Constants.ROOM_NAME_MIYU, "[IFTTT] EURUSD High Chance"); //List<string> res = new List<string>(); //hlc.getSignalResult(ref res); } catch (Exception e) { throw e; } // メッセージ調査用 //// 失敗する //string testword = "[バイナリー配信] Mon Jan 07 2019 17:04:59 エントリー,マーチン,EURUSD,5分,ロー,数値:1.144"; ////CommonControl.DebugPrint(testword.IndexOf("[バイナリー配信]") == 0); //SignalOrder sig = HighLowControl.AnalysisWord(Constants.ROOM_NAME_AUXESIS, testword); //Console.WriteLine("今開いているハンドル:" + driver.CurrentWindowHandle); //foreach (String hndl in driver.WindowHandles) //{ // driver.SwitchTo().Window(hndl); // System.Threading.Thread.Sleep(2000); // Console.WriteLine("Title:" + driver.Title); // Console.WriteLine("URL:" + driver.Url); //} }
/// <summary> /// MIYU 部屋用 /// /// メッセージ例:[IFTTT] EURUSD Low Chance ・・・ /// </summary> /// <param name="argSignalWord">解析する文章</param> /// <returns></returns> private static SignalOrder AnalysisByMiyuMsg(string argSignalWord) { SignalOrder Sio = new SignalOrder(); try { string[] tmp = argSignalWord.Split(new string[] { "\r\n" }, StringSplitOptions.None); string[] wword = tmp[0].Split(new string[] { " " }, StringSplitOptions.None); // 6文字の場合は間にスラッシュ if (wword[1].Trim().Length == 6) { char[] tmpBrand = wword[1].Trim().ToCharArray(); for (int n = 0; n < tmpBrand.Length; n++) { Sio.tradeBrand += tmpBrand[n]; if (2 == n) { Sio.tradeBrand += "/"; } } } // ハイかローを決める Sio.arrow = wword[2].Trim().Equals("High") ? arrowState.asHigh : arrowState.asLow; // 現在時間で次のエントリー時間を求める Sio.signalMsgTimeRceived = DateTime.Now; getNextEntryTime(Sio); //無条件 エントリーを指定 Sio.mainState = SignalState.soEntry; } catch (Exception e) { CommonControl.DebugPrint(e, "想定外のメッセージ形式"); Sio.mainState = SignalState.soInitilized; //throw; } return(Sio); }
/// <summary> /// デモかリアルかを判断する /// </summary> /// <param name="sio">判断するシグナル</param> public static void JudgeRealDemo(ref SignalOrder sio) { try { // デフォルト値 sio.Environment = EnvState.esTest; // 判定時間で判断する 判定に使用する時間 int Jtime = sio.tradeEntryTime.Hour; // Keyから取得 Constants.rdDic.TryGetValue(sio.signalRoomName + "@" + Jtime, out bool timeKey); sio.Environment = timeKey ? EnvState.esReal : EnvState.esTest; // True Real / False Demo } catch (Exception) { sio.Environment = EnvState.esTest; } }
/// <summary> /// 次にエントリーする時間を求める /// </summary> /// <param name="argSio">シグナル情報</param> /// <returns></returns> private static void getNextEntryTime(SignalOrder argSio) { try { // エントリー時間 int entryHour = 0; // 時 int entryMinute = 0; // 分 // シグナルメッセージ時刻 DateTime sTime = argSio.signalMsgTimeRceived; // 次の5分刻みの時刻をもとめる entryHour = sTime.Hour; entryMinute = sTime.Minute; entryMinute = entryMinute + 5 - (entryMinute % 5); // 次の時間またいでいるとき Hour繰り上げ if (entryMinute >= 60) { entryHour = entryHour + 1; entryMinute = entryMinute % 60; } // エントリー時間 TODO:Parseがミスする? argSio.tradeEntryTime = DateTime.Parse(entryHour.ToString() + ":" + entryMinute.ToString() + ":00"); // タイムフレーム時間 エントリー時間の5分後 DateTime fTime = argSio.tradeEntryTime.AddMinutes(5); argSio.tradeTimeFrame = fTime.Hour.ToString("00") + ":" + fTime.Minute.ToString("00"); } catch (Exception e) { // CommonControl.DebugPrint(e, "次のエントリー時間を求めるのに失敗した" + argSio.lineSignalTimeRceived); throw; } }
/// <summary>コンストラクタ Sig付き</summary> public BoHistroyContainer(HistoryState State_, SignalOrder Sig_) { this.State = State_; this.Sig = Sig_; // 当初はブック単位でシグナルを切り替える予定だったが、1つのブックで管理するように変更 this.PostURL_SpredSheet = Constants.URL_GAS_POST_COMMON; // 切り替える必要が出てきたらここで変える //switch (this.Sig.signalRoomName) //{ // case Constants.ROOM_NAME_CmdLine: // case Constants.ROOM_NAME_SignalMeijin: // this.PostURL_SpredSheet = Constants.URL_GAS_POST_AUXSIS; // break; // case Constants.ROOM_NAME_AUXESIS: // this.PostURL_SpredSheet = Constants.URL_GAS_POST_AUXSIS; // break; // case Constants.ROOM_NAME_DebugRoomName: // this.PostURL_SpredSheet = Constants.URL_GAS_POST_AUXSIS; // debug // break; //} }
static void Main(string[] args) { //ForDebugOnly(); // デバッグ用関数 //return; try { // ===== ===== ===== ===== ===== ===== ===== ===== ===== ===== ===== ===== ===== ===== ===== ===== // 起動準備 & 引数用意 // ===== ===== ===== ===== ===== ===== ===== ===== ===== ===== ===== ===== ===== ===== ===== ===== // パラメータ設定の初期化(取得) Constants.Initialize(); // ブラウザ立ち上げ ChromeDriverEx chrome = CreateNewChromeDriver(); // 経済指標を取得 //InvestingCalender InvC = new InvestingCalender(ref chrome); //InvC.GetInvestingCalender(); //// LINE用 LINEControl cLINE = new LINEControl(ref chrome); // ログイン ライン cLINE.LoginLINE(); //// 初回ログイン時はログイン情報だけを記憶させて終了 //if (Constants.Login_Line_First) return; //// highlow 本トレ HighLowControl cHighLow_Real = new HighLowControl(ref chrome); cHighLow_Real.Open(false); // 本番OPEN cHighLow_Real.Login(); // 本トレログイン ///// highlowデモ HighLowControl cHighLow_Demo = new HighLowControl(ref chrome); cHighLow_Demo.Open(true); // デモOPEN cHighLow_Demo.demoLogin(); // デモログイン CommonControl.SleepWait(500); // ユーザーによるコマンド受付 情報保持用 string userCommandStatus = string.Empty; //ハイロー入札履歴 List <BoHistroyContainer> HL_History = new List <BoHistroyContainer>(); #if DEBUG //ForDebugOnly(chrome); //return; #endif // シグナルが来るまで待つか、[コマンド]終了を受け付けたら終了 while (true) { //CommonControl.DebugPrint("待機開始・・・"); // メッセージを待つ string signalRoomName = WaitLineGroupsNewArraival(cLINE); // なければ、終了定期処理へ if (string.IsNullOrEmpty(signalRoomName)) { CommonControl.DebugPrint("この時間来ませんでした" + DateTime.Now); goto finallyProcess; // 終了まで飛ばす } // 以下、シグナル受信していたら // メッセージが来た時 // 新着対象の部屋のメッセージ群を取得する ArrayList newMsgList = cLINE.getNewMsgText(signalRoomName); // メッセージがあるか?(通知に気づいたときには古いメッセージしかなくて新着メッセージないときは抜ける) if (newMsgList.Count == 0) { // 新着に気づいたが、メッセージが古い時間のものしか無かった時 CommonControl.DebugPrint("気づくのが遅かった・・・部屋名:" + signalRoomName); goto finallyProcess; // 終了まで飛ばす } string newMsg = ""; if (!userCommandStatus.Equals("stop")) { // エントリーの情報1つのみに絞り込むか又は命令メッセージ(最初に見つかったエントリー メッセージを取得) newMsg = HighLowControl.SelectSignalMsg(signalRoomName, newMsgList); } else { newMsg = (string)newMsgList[newMsgList.Count - 1]; } if (Constants.LINE_RECEIVER_SIDE) { // 子機の場合は冒頭についているどの部屋から来たか情報を取り出し // メッセージの冒頭の親からのヘッダパラメータをカットしてシグナル文のみにする signalRoomName = HighLowControl.AnalysisReceiverSide(ref newMsg); } // ※Stop時以外 // 命令かバイナリー配信かを判断する if (IsSignalMsg(signalRoomName, newMsg)) { // バイナリー配信の時 // 親機の時のみ if (Constants.LINE_RECEIVER_SIDE == false) { // 対象の部屋(グループ)へメッセージをコピー cLINE.putSignalMsgToRoom(Constants.ROOM_NAME_BoSignal, signalRoomName, newMsg); } // シグナル解析 SignalOrder sig = HighLowControl.AnalysisWord(signalRoomName, newMsg); // 指標の高い重要度の時間帯でないか\ // 又は、指定した時間帯 //if (!InvC.JudgeEnvironmentSignalZone(ref sig, ref cLINE)) //sig.Environment = EnvState.esTest; // 無条件デモ HighLowControl.JudgeRealDemo(ref sig); // エントリー結果 bool entryResult = false; if (sig.Environment.Equals(EnvState.esReal)) { // リアルトレード entryResult = cHighLow_Real.EntryHighLow(ref sig); } else { // デモトレード entryResult = cHighLow_Demo.EntryHighLow(ref sig); } // 結果をラインに表示 if (entryResult) { //成功時 cLINE.putSignalMsgToRoom(Constants.ROOM_NAME_CmdLine, signalRoomName, "エントリーに成功。" + Constants.LINE_CRLF + sig.getEntryNoticeMsg()); // シグナル履歴にストック BoHistroyContainer boc = new BoHistroyContainer(HistoryState.hsWaitResult, sig); HL_History.Add(boc); } else { CommonControl.DebugPrint("エントリーに失敗。" + sig.rawOriginalMessage); // デバッグ用 //cLINE.putSignalMsgToRoom(Constants.ROOM_NAME_CmdLine, signalRoomName, "エントリーに失敗。" + sig.rawOriginalMessage); } // 待機に戻る } else { // バイナリー配信ではなくて、命令の時 ステータスにセット if (signalRoomName.Equals(Constants.ROOM_NAME_CmdLine)) // 命令は指定のルームからのメッセージのみ受け取る { // 命令の抽出 string comResult = CommandProc(newMsg, userCommandStatus, out userCommandStatus); // エラーがあった場合 if (comResult.Length != 0) { cLINE.putSignalMsgToRoom(Constants.ROOM_NAME_CmdLine, "", comResult); } // 命令実行 TODO:今は仮 if (userCommandStatus.IndexOf("end") >= 0) // 終了時 { cLINE.putSignalMsgToRoom(Constants.ROOM_NAME_CmdLine, signalRoomName, "プログラムを終了します。" + newMsg); break; } } } // 1通り終了時 定期的に行う処理 finallyProcess: // ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- // 溜まったタスクを消化 // ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- System.Windows.Forms.Application.DoEvents(); ClickActionTrigger += 1; // ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- // 結果を見に行き、新着があればそれを部屋に出力 // ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- cHighLow_Real.getSignalResult(ref HL_History); // 本トレ cHighLow_Demo.getSignalResult(ref HL_History); // デモ それぞれに見に行く for (int i = 0; i < HL_History.Count; i++) { if (HL_History[i].State == HistoryState.hsDone) { continue; // 全て完了済みのものは飛ばす } bool ret = false; HL_History[i].PostResultData = CommonControl.PostBoResult(HL_History[i]); // Google送信 // postデータが作られていたら成功 HL_History[i].State = string.IsNullOrEmpty(HL_History[i].PostResultData) ? HL_History[i].State : HistoryState.hsPostDataComplete; // 成功したかどうか ret = CommonControl.OutPutTextBoResult(HL_History[i]); // テキスト吐き出し // テキスト掃き出しできたらすべて完了 HL_History[i].State = ret ? HistoryState.hsDone : HL_History[i].State; } // TODO: コンプリートしたBOコンテナ要素はここで削除しても良いかも // ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- // 2minに一回何らかのアクションを起こしてメッセージの受信頻度を上げる // スリープ(LINE受信しなくなる)対策 // ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- if (ClickActionTrigger % 2 == 0) { CommonControl.ClickAction(); ClickActionTrigger = 0; // 受信が行われるようにActiveWindowsの切り替えを行う //TODO:実験成功? 画面のライトがONOFFしなくても受信できるかチェックする SendKeys.SendWait("%{TAB}"); CommonControl.SleepWait(500); SendKeys.SendWait("%{TAB}"); // ネットワークが切れていれば 再ログイン 効果未確認 cHighLow_Real.RetryLogin(); } // debug用 //break; } // main end // ハイローログアウト //cHighLow_Demo.Logout(); //cHighLow_Real.Logout(); chrome.Quit(); } catch (Exception e) { // 想定外エラー発生時 // 原因調査用 CommonControl.DebugPrint(e, "Main Exception"); } finally { CommonControl.DebugPrint("プログラムを終了しました"); } }
/// <summary> /// アクシス部屋の文章を解析する /// 以下は1マーチンメッセージ例 上から下へ受信する /// [バイナリー配信] Mon Jan 07 2019 16:59:00 待機,,EURUSD,5分,ロー,数値:1.144 /// [バイナリー配信] Mon Jan 07 2019 16:59:53 エントリー,ptn20,EURUSD,5分,ロー,数値:1.144 /// [バイナリー配信] Mon Jan 07 2019 17:04:36 待機,マーチン,EURUSD,5分,ロー,数値:1.144 /// [バイナリー配信] Mon Jan 07 2019 17:04:59 エントリー,マーチン,EURUSD,5分,ロー,数値:1.144 /// [バイナリー配信] Mon Jan 07 2019 17:10:00 ProPirot_WIN,EURUSD,5分,ロー,マーチン,CloseValue[1]:1.1435700 /// </summary> /// <param name="argWord">メッセージ平文</param> /// <returns></returns> private static SignalOrder AnalysisByAuxesisMsg(string argWord) { SignalOrder Sio = new SignalOrder(); try { // 受け取った時間 Sio.lineSignalTimeRceived = DateTime.Now; string[] signalArray = argWord.Split(','); string[] tmp; for (int i = 0; i < signalArray.Count(); i++) { switch (i) { case 0: // TODO:区切り文字を何にするか 今後の課題 string[] rep = { " 2020 " }; tmp = signalArray[i].Split(rep, StringSplitOptions.None); // Hawkの前 シグナルを受けた時間 とステータス String[] splitTimeAndState = tmp[1].Split(new string[] { " " }, StringSplitOptions.None); // 時間だけでよい 2019/03/07 受けた時間に修正する Sio.signalMsgTimeRceived = DateTime.Now; // DateTime.Parse(splitTimeAndState[0]); // エントリー時間関係の情報を計算する getNextEntryTime(Sio); // ステータス switch (splitTimeAndState[1].Trim()) { case "キャンセル": Sio.mainState = SignalState.soCancel; break; case "待機": Sio.mainState = SignalState.soEntry; // 待機をエントリーとして扱う break; case "エントリー": Sio.mainState = SignalState.soCancel; // エントリーメッセージが来た時点では既に遅いのでキャンセルにする break; case "WIN": Sio.mainState = SignalState.soResult; Sio.subState = SignalState.soWin; break; case "LOSE": Sio.mainState = SignalState.soResult; Sio.subState = SignalState.soLose; break; } break; // 1番目以外 default: // ptn20 if (signalArray[i].Equals("ptn20")) { Sio.subState = SignalState.soPtn20; } // マーチン else if (signalArray[i].Equals("マーチン")) { Sio.subState = SignalState.soMartin; } else { // 銘柄 if (string.IsNullOrEmpty(Sio.tradeBrand)) { // 6文字の場合は間にスラッシュ if (signalArray[i].Trim().Length == 6) { char[] tmpBrand = signalArray[i].Trim().ToCharArray(); for (int n = 0; n < tmpBrand.Length; n++) { Sio.tradeBrand += tmpBrand[n]; if (n == 2) { Sio.tradeBrand += "/"; } } } else { // それ以外 Sio.tradeBrand = signalArray[i].Trim(); } } // 入札時間 else if (string.IsNullOrEmpty(Sio.tradeTimeSpan)) { Sio.tradeTimeSpan = signalArray[i].Trim(); } // ハイロー else if (Sio.arrow == arrowState.asUnkown) { Sio.arrow = signalArray[i].Trim().Equals("ハイ") ? arrowState.asHigh : arrowState.asLow; } // 入札数値 else if (string.IsNullOrEmpty(Sio.bidPrice)) { // 数値の文字が入ってたら取得する if (signalArray[i].Contains("数値")) { try { Sio.bidPrice = signalArray[i].Split(':')[1]; } catch (Exception) { // 無視する //throw; } } } } break; } } Sio.signalCompleteFlag = true; } catch (Exception ex) { CommonControl.DebugPrint(ex, "想定外のメッセージ配列を受信しました。\nメッセージ:" + argWord); throw; } return(Sio); }
/// <summary> /// シグナル名人のシグナルを解析する /// </summary> /// <param name="argSignalWord"></param> /// <returns></returns> private static SignalOrder AnalysisBySignalMeijin(string argSignalWord) { SignalOrder Sio = new SignalOrder(); Sio.rawOriginalMessage = argSignalWord; string wTime; try { string[] tmp = argSignalWord.Split(new string[] { Constants.LINE_CRLF }, StringSplitOptions.None); for (int i = 0; i < tmp.Length; i++) { switch (i) { case 2: // 銘柄 char[] tmpBrand = tmp[i].Trim().ToCharArray(); for (int n = 0; n < tmpBrand.Length; n++) { Sio.tradeBrand += tmpBrand[n]; if (n == 2) { Sio.tradeBrand += "/"; } } break; case 3: // 取引時間 wTime = tmp[i].Split(new string[] { " " }, StringSplitOptions.None)[1]; Sio.tradeEntryTime = DateTime.Parse(wTime); if (wTime.Equals("0時0分")) { Sio.tradeEntryTime.AddDays(1); // 0時0分の時の入札は明日 } break; case 4: // 判定時間 wTime = tmp[i].Split(new string[] { " " }, StringSplitOptions.None)[1]; DateTime dt = DateTime.Parse(wTime); wTime = dt.Hour.ToString("00") + ":" + dt.Minute.ToString("00"); Sio.tradeTimeFrame = wTime; break; case 5: // ハイロー Sio.arrow = tmp[i].Trim().Equals("Low") ? arrowState.asLow : arrowState.asHigh; break; case 6: // 指標値 Sio.bidPriceRawMessage = tmp[i]; Sio.bidPrice = tmp[i].Split(new string[] { " " }, StringSplitOptions.None)[0]; break; case 7: if (tmp[i].Equals("エントリー準備です")) { Sio.mainState = SignalState.soEntry; // エントリー行う } else { Sio.mainState = SignalState.soInitilized; // それ以外は無視 } break; default: break; } } } catch (Exception e) { CommonControl.DebugPrint(e, "想定外の形式メッセージが来た"); } return(Sio); }
/// <summary> /// ハイローにエントリーする /// </summary> /// <param name="sig">シグナル情報 コンテナ</param> /// <returns>True エントリー成功 / False エントリー失敗</returns> public Boolean EntryHighLow(ref SignalOrder sig) { try { // シグナルのステータスがエントリーのみ実行 if (sig.mainState != SignalState.soEntry) { return(false); } // ハイローをアクティブに this.IsActivate(); // 要素が押せるようにスクロールをトップに chrome.ExecuteScript("document.scrollingElement.scrollTop = 140"); // 対象の取引する銘柄へ移動 // ===== ===== ===== ===== ===== ===== // 銘柄リストを開く // ===== ===== ===== ===== ===== ===== IWebElement BrandList = this.chrome.FindElementByXPath("//*[@id='highlow-asset-filter']"); CommonDriverControl.ScrollTargetElementView(BrandList); BrandList.Click(); CommonControl.SleepWait(500); // ===== ===== ===== ===== ===== ===== // 銘柄を選ぶ // ===== ===== ===== ===== ===== ===== // 検索にかける IWebElement eleSearchBox = this.chrome.FindElementById("searchBox"); eleSearchBox.SendKeys(sig.tradeBrand); CommonControl.SleepWait(200); // ヒットした一番目を選択(1つしかないはず) IWebElement eleResultList = this.chrome.FindElementByXPath("//*[@id='assetsFilteredList']/div[1]"); eleResultList.Click(); // ===== ===== ===== ===== ===== ===== // 15分固定 // ===== ===== ===== ===== ===== ===== IWebElement timeTab = this.chrome.FindElementByXPath( "//*[@id='assetsCategoryFilterZoneRegion']/div/div[2]"); CommonDriverControl.ScrollTargetElementView(timeTab); timeTab.Click(); CommonControl.SleepWait(500); // ===== ===== ===== ===== ===== ===== // エントリーする判定時刻 フレーム時間のタブを見つける // ===== ===== ===== ===== ===== ===== IReadOnlyCollection <IWebElement> frameTimeDigits = this.chrome.FindElementsByXPath("//*[@class='time-digits']"); // 最大3つある フレームタイムの時間を見に行き、同じ時間を探す bool findFrameFlag = false; for (int i = 0; i < frameTimeDigits.Count(); i++) { //シグナル時間の取得 string chkFrameTime = frameTimeDigits.ElementAt(i).GetAttribute("textContent"); // 次のシグナルの時間か? if (sig.tradeTimeFrame.Equals(chkFrameTime)) { // 表示 frameTimeDigits.ElementAt(i).Click(); findFrameFlag = true; // 見つかった break; // 1つしかない } } // 見つからなかったとき if (findFrameFlag == false) { // エントリー失敗 CommonControl.DebugPrint("entryHighLow", "対象のタイムフレーム時間が見つからなかった為、エントリー出来ませんでした"); CommonControl.DebugPrint("探そうとしたタイムフレーム" + sig.tradeTimeFrame); return(false); } CommonControl.SleepWait(500); // ===== ===== ===== ===== ===== ===== // エントリー金額を入力する // ===== ===== ===== ===== ===== ===== // TODO:実際は総資金の10分の1入札する この仕組みは後に作る 今は単純に10分の1でエントリーする // 10分1が20万を超えた場合は以下のようにする // 例:22万円の場合、11万*2回エントリーする // 30万円の場合、15万円*2回エントリーする // 残高 // タイムフレームを押した後、読み込み中である可能性があるので取得可能になるまで待つ(GetSafeWebElementById) IWebElement eleBalance = CommonDriverControl.GetSafeWebElementById(chrome, Constants.HTML_ID_HL_Balance); int balance = int.Parse(eleBalance.GetAttribute("textContent") .Replace(@"¥", "").Replace(",", "")); // 入力 IWebElement eleAmount = chrome.FindElementById(Constants.HTML_ID_HL_Amount); // TODO:たまに失敗してる? 要調査 念のため2回おこなう CommonDriverControl.ScrollTargetElementView(eleAmount); // 見えていないとクリアできない CommonDriverControl.ScrollTargetElementView(eleAmount); // 見えていないとクリアできない eleAmount.Clear(); // 既存入力額をクリア CommonControl.SleepWait(200); int amount = balance / 2000; // 資産の 20分の1で amount = amount * 100; // 100の倍数にする if (amount < 1000) { amount = 1000; // 1000円未満になった場合は1000円 } if (amount > 200000) { amount = 200000; // 20万を超える場合は20万 (20万以上はエントリーできないため) } eleAmount.SendKeys(amount.ToString()); // ===== ===== ===== ===== ===== ===== // High Or Low 入力 // ===== ===== ===== ===== ===== ===== // 要素が押せるようにスクロールトップの調整 chrome.ExecuteScript("document.scrollingElement.scrollTop = 275"); IWebElement btn; switch (sig.arrow) { case arrowState.asLow: btn = this.chrome.FindElementByXPath(Constants.XPATH_HL_Low_Button); break; case arrowState.asHigh: btn = this.chrome.FindElementByXPath(Constants.XPATH_HL_High_Button); break; default: CommonControl.DebugPrint("ハイ、又はローが分かりませんでした。"); return(false); } btn.Click(); CommonControl.SleepWait(200); // ===== ===== ===== ===== ===== ===== // エントリー時間になるまで待つ // ===== ===== ===== ===== ===== ===== IWebElement rTime = this.chrome.FindElementByXPath(Constants.XPATH_HL_Remaining_Time); string[] timeTxt = rTime.GetAttribute("textContent").Split(new string[] { ":" }, StringSplitOptions.None); // 後どれだけ待てば良いかを求める 5分前まで TimeSpan tsReman = new TimeSpan(0, int.Parse(timeTxt[0]), int.Parse(timeTxt[1])) - new TimeSpan(0, 5, 0); while (true) { // 残り時刻が5分切るまで待機 if (tsReman > new TimeSpan(0, 0, 0)) { CommonControl.SleepWait((int)tsReman.TotalMilliseconds); } break; } // 成功するまで エントリーを行う int tryTime = 0; bool entryFlag = false; while (entryFlag == false) { IWebElement entryBtn = this.chrome.FindElementById("invest_now_button"); entryBtn.Click(); CommonControl.SleepWait(1250); IWebElement eleNotice = this.chrome.FindElementById(Constants.HTML_ID_HL_NoticeMsg); if (eleNotice.Text.Equals("成功")) { //エントリーに成功した entryFlag = true; } tryTime += 1; if (tryTime > 2) { break; // 3回目失敗したら強制終了 } } #if debug if (tryTime == 3) { CommonControl.DebugPrint("3回エントリー失敗した"); } #endif // 処理自体のエントリー結果を返す return(entryFlag); } catch (Exception e) { // エントリーに失敗した CommonControl.DebugPrint(e, "EntryHighLow エントリーに失敗しました"); //throw;// 投げない return(false); } }