#property copyright "yuki"
#property link "https://yukifx.web.fc2.com/"
#property version "1.00"
#property strict
#define MAGIC_NO 20191012
#property description "ボリンジャーバンド2σタッチ(前回終値判定)で逆張りし、MAタッチで決済するサンプルEA。"
#property description "プログラミングの勉強用サンプルEAの為、勝てるEAではありません。"
#property description "絶対にライブ口座で稼働させないで下さい、絶対に負けます。"
#define EA_ORDER_TIMES_INTERVAL 5
#define ORDER_SLIPRATE 50
input int Input_MAPeriod = 25;
input double Input_Limit = 100;
input double Input_Stop = 100;
sinput double Input_EntryLot = 0.01;
sinput bool Input_Debug = true;
struct struct_PositionInfo {
int ticket_no;
int entry_dir;
double entry_orderrate;
double entry_donerate;
double entry_lot;
double set_limit;
double set_stop;
};
struct_PositionInfo _StPositionInfoData;
int OnInit() {
if ( IsDemo() == false ) {
MessageBox("実際に新規オーダーするので、デモ口座で動作させて下さい。","エラー",MB_ICONEXCLAMATION);
return(INIT_FAILED);
}
GetPosiInfo(_StPositionInfoData);
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason) {
}
void OnTick() {
TaskMain();
}
void TaskMain() {
static datetime slasttime;
datetime temptime = iTime(Symbol(),Period(),0);
if ( temptime != slasttime ) {
slasttime = temptime;
GetPosiInfo(_StPositionInfoData);
if ( CheckTicketPosition( _StPositionInfoData.ticket_no) == true ) {
ClearPosiInfo(_StPositionInfoData);
}
if ( GetKeepPosition(_StPositionInfoData) == false ) {
JudgeEntry(_StPositionInfoData);
}
}
if ( GetKeepPosition(_StPositionInfoData) == true ) {
JudgeClose(_StPositionInfoData);
}
}
void ClearPosiInfo( struct_PositionInfo &in_st ){
in_st.ticket_no = 0;
in_st.entry_orderrate = 0;
in_st.entry_donerate = 0;
in_st.set_limit = 0;
in_st.set_stop = 0;
}
bool GetKeepPosition( struct_PositionInfo &in_st ){
bool ret = false;
if ( in_st.ticket_no != 0 ) {
ret = true;
}
return ret;
}
bool GetPosiInfo( struct_PositionInfo &in_st ){
int total_order;
int pos;
bool ret = false;
total_order = OrdersTotal();
if ( IsConnected() == true ) {
for ( pos = 0 ; pos < total_order ; pos++ ) {
if ( OrderSelect( pos , SELECT_BY_POS ) == true ) {
if ( OrderMagicNumber() != MAGIC_NO ) {
continue;
}
if ( OrderSymbol() != Symbol() ) {
continue;
}
in_st.ticket_no = OrderTicket();
in_st.entry_dir = OrderType();
in_st.entry_donerate = OrderOpenPrice();
in_st.entry_lot = OrderLots();
in_st.set_limit = OrderTakeProfit();
in_st.set_stop = OrderStopLoss();
CheckLimitStop(in_st);
ret = true;
break;
}
}
}
return ret;
}
void CheckLimitStop( struct_PositionInfo &in_st ){
double temp_limit = Input_Limit * Point() * 10;
double temp_stop = Input_Stop * Point() * 10;
double set_limitrate = 0;
double set_stoprate = 0;
if ( in_st.entry_donerate > 0 ) {
if ( in_st.entry_dir == OP_BUY ) {
if ( temp_limit > 0 ) {
set_limitrate = in_st.entry_donerate + temp_limit;
}
if ( temp_stop > 0) {
set_stoprate = in_st.entry_donerate - temp_stop;
}
} else {
if ( temp_limit > 0 ) {
set_limitrate = in_st.entry_donerate - temp_limit;
}
if ( temp_stop > 0) {
set_stoprate = in_st.entry_donerate + temp_stop;
}
}
set_limitrate = NormalizeDouble( set_limitrate , Digits );
set_stoprate = NormalizeDouble( set_stoprate , Digits );
if ( set_limitrate != in_st.set_limit || set_stoprate != in_st.set_stop ) {
EA_Modify_Order( in_st.ticket_no , set_limitrate , set_stoprate, __LINE__ );
}
}
}
bool CheckTicketPosition( int in_ticket ){
bool done_ret = false;
if ( in_ticket > 0 ) {
bool bool_order_sel = OrderSelect( in_ticket , SELECT_BY_TICKET) ;
if ( bool_order_sel == false ) {
debug_print(__LINE__ , StringFormat("TicketSelectErr:%d" , GetLastError()));
}
if ( OrderCloseTime() > 0 ) {
done_ret = true;
}
}
return done_ret;
}
void JudgeEntry(struct_PositionInfo &in_stposi){
bool upper_bool = true;
int lineindexmode = MODE_UPPER;
double bband_diverrate = 0;
double bband_baserate = 0;
bool entry_bool = false;
bband_baserate = iBands(
Symbol()
,Period()
,Input_MAPeriod
,2
,0
,PRICE_CLOSE
,MODE_MAIN
,0
);
if ( Close[0] > bband_baserate ) {
lineindexmode = MODE_UPPER;
upper_bool = true;
} else {
lineindexmode = MODE_LOWER;
upper_bool = false;
}
bband_diverrate = iBands(
Symbol()
,Period()
,Input_MAPeriod
,2
,0
,PRICE_CLOSE
,lineindexmode
,0
);
if ( Close[1] > 0 && bband_baserate > 0 && bband_diverrate > 0) {
if ( upper_bool == true ) {
if ( Close[1] > bband_diverrate && Bid > bband_diverrate) {
entry_bool = true;
}
} else {
if ( Close[1] < bband_diverrate && Ask < bband_diverrate) {
entry_bool = true;
}
}
if ( entry_bool == true ) {
EA_Entry_Order( upper_bool , in_stposi );
}
}
}
void JudgeClose(struct_PositionInfo &in_stposi){
bool close_bool = false;
bool close_ret = false;
double bband_baserate = 0;
if ( in_stposi.ticket_no > 0 ) {
bband_baserate = iBands(
Symbol()
,Period()
,Input_MAPeriod
,2
,0
,PRICE_CLOSE
,MODE_MAIN
,0
);
if ( in_stposi.entry_dir == OP_BUY) {
if ( Bid > bband_baserate && bband_baserate > 0) {
close_bool = true;
}
} else {
if ( Ask < bband_baserate && bband_baserate > 0) {
close_bool = true;
}
}
if ( close_bool == true ) {
close_ret = EA_CloseOrder( in_stposi.ticket_no );
if ( close_ret == true ) {
ClearPosiInfo(in_stposi);
}
}
}
}
bool EA_Entry_Order( bool in_upper , struct_PositionInfo &in_stposi) {
bool entry_comp = false;
double temp_limit = Input_Limit * Point() * 10;
double temp_stop = Input_Stop * Point() * 10;
ClearPosiInfo(in_stposi);
if ( in_upper == false ) {
in_stposi.entry_dir = OP_BUY;
in_stposi.entry_orderrate = Ask;
if ( temp_limit > 0 ) {
in_stposi.set_limit = in_stposi.entry_orderrate + temp_limit;
}
if ( temp_stop > 0) {
in_stposi.set_stop = in_stposi.entry_orderrate - temp_stop;
}
} else {
in_stposi.entry_dir = OP_SELL;
in_stposi.entry_orderrate = Bid;
if ( temp_limit > 0 ) {
in_stposi.set_limit = in_stposi.entry_orderrate - temp_limit;
}
if ( temp_stop > 0) {
in_stposi.set_stop = in_stposi.entry_orderrate + temp_stop;
}
}
double templot;
templot = NormalizeDouble(Input_EntryLot,2);
if ( templot < 0.01 ) {
templot = 0.01;
}
in_stposi.entry_lot = templot;
int order_resend_num;
int ea_ticket_res;
int err_code;
in_stposi.entry_orderrate = NormalizeDouble( in_stposi.entry_orderrate , Digits );
in_stposi.set_limit = NormalizeDouble( in_stposi.set_limit , Digits );
in_stposi.set_stop = NormalizeDouble( in_stposi.set_stop , Digits );
for ( order_resend_num = 0; order_resend_num < EA_ORDER_TIMES_INTERVAL; order_resend_num++ ) {
ea_ticket_res = OrderSend(
Symbol(),
in_stposi.entry_dir,
in_stposi.entry_lot,
in_stposi.entry_orderrate,
ORDER_SLIPRATE,
0,
0,
"ボリバン逆張りサンプルEA",
MAGIC_NO,
0,
clrAqua
);
err_code = GetLastError();
if ( ea_ticket_res == -1 ) {
if ( err_code == ERR_NO_CONNECTION ) {
int regetno = EA_ConnectFailCheck(in_stposi.entry_dir);
if ( regetno > -1 ) {
ea_ticket_res = regetno;
debug_print( __LINE__ , StringFormat("再取得したチケットナンバーで更新 %d" , ea_ticket_res));
}
}
}
if ( ea_ticket_res == -1) {
debug_print(__LINE__,StringFormat("エントリーオーダー試行回数:%d" , order_resend_num));
Sleep(500);
} else {
entry_comp = true;
bool ea_orderret = OrderSelect(ea_ticket_res,SELECT_BY_TICKET,MODE_TRADES);
if ( ea_orderret == false ){
debug_print(__LINE__ , StringFormat("TicketOrderSelectErr:%d" , GetLastError()) );
} else {
in_stposi.entry_donerate = OrderOpenPrice();
in_stposi.ticket_no = OrderTicket();
if ( in_stposi.set_limit != 0 || in_stposi.set_stop != 0) {
EA_Modify_Order( in_stposi.ticket_no , in_stposi.set_limit , in_stposi.set_stop, __LINE__ );
}
}
break;
}
}
if ( entry_comp == false ) {
debug_print(__LINE__, StringFormat("オーダー取消し。執行回数:%d" , order_resend_num) );
ClearPosiInfo(in_stposi);
}
return entry_comp;
}
void EA_Modify_Order( int in_ticket , double in_limit , double in_stop , int in_line) {
int icount;
int interval;
double limit_set = 0;
double stop_set = 0;
double entry_rate = 0;
int errcode;
bool selbool = OrderSelect( in_ticket ,SELECT_BY_TICKET,MODE_TRADES);
if (selbool == false){
debug_print(__LINE__ , StringFormat("TicketOrderSelectErr:%d" ,GetLastError()) );
} else {
entry_rate = OrderOpenPrice();
if ( in_limit > 0 ) {
limit_set = in_limit;
}
if ( in_stop > 0 ) {
stop_set = in_stop;
}
Sleep(100);
for ( icount = 0; icount < EA_ORDER_TIMES_INTERVAL; icount++ ) {
errcode = 0;
bool eabool = OrderModify(
OrderTicket(),
entry_rate,
in_stop,
limit_set,
0,
clrYellow);
if ( eabool == true ) {
break;
} else {
errcode = GetLastError();
if ( IsTesting() == true && errcode == ERR_INVALID_TICKET ) {
break;
} else {
interval = 300 * icount;
Sleep(interval);
string moderrstr = StringFormat("OrderModifyErr:%d TicketNo:%d Open:%f Limit:%f-%f Stop:%f-%f"
, errcode , in_ticket , entry_rate
, limit_set , OrderTakeProfit(), in_stop, OrderStopLoss() );
debug_print(in_line , moderrstr);
}
if ( errcode == ERR_NO_RESULT ) {
debug_print(in_line , "リミット/ストップの値が変更前と同じ値に設定している可能性有り");
break;
}
}
}
}
}
bool EA_CloseOrder( int in_ticket ) {
double ea_order_close_price;
bool bool_order_sel;
datetime order_sel_closetime;
int order_close_resend_num;
bool closeret;
int interval;
bool order_ret;
string ea_debug;
order_ret = false;
bool_order_sel = false;
if ( in_ticket > 0 ) {
bool_order_sel = OrderSelect( in_ticket , SELECT_BY_TICKET) ;
if ( bool_order_sel == false ) {
ea_debug = StringFormat("TicketSelectErr:%d" , GetLastError());
debug_print(__LINE__ , ea_debug);
}
order_sel_closetime = OrderCloseTime();
if ( order_sel_closetime <= 0 ) {
for ( order_close_resend_num = 0; order_close_resend_num < EA_ORDER_TIMES_INTERVAL; order_close_resend_num++ ) {
if ( OrderType() == OP_BUY){
ea_order_close_price = Bid;
} else {
ea_order_close_price = Ask;
}
closeret = OrderClose(
in_ticket,
OrderLots(),
ea_order_close_price,
ORDER_SLIPRATE,
clrWhite
);
if ( closeret == true ) {
order_ret = true;
break;
} else {
ea_debug = StringFormat("クローズオーダーエラー:%d Ticket:%d 試行回数:%d"
, GetLastError() ,in_ticket ,order_close_resend_num);
debug_print(__LINE__ , ea_debug);
bool_order_sel = OrderSelect( in_ticket , SELECT_BY_TICKET) ;
order_sel_closetime = OrderCloseTime();
if ( order_sel_closetime > 0 ) {
debug_print(__LINE__ , "既決済:" + TimeToStr(order_sel_closetime));
order_ret = true;
break;
} else {
if ( order_close_resend_num > 0 ) {
interval = 300 * order_close_resend_num;
} else {
interval = 300;
}
Sleep(interval);
debug_print(__LINE__ , StringFormat("クローズオーダー試行回数:%d %d"
, order_close_resend_num , interval));
RefreshRates();
}
}
}
} else {
order_ret = true;
}
} else {
order_ret = false;
}
return order_ret;
}
int EA_ConnectFailCheck( int in_cmd ) {
int tempret;
int icount;
int waittime;
tempret = -1;
waittime = 1;
for ( icount = 0; icount < 11; icount++ ) {
waittime = waittime * 2;
debug_print( __LINE__ , StringFormat("再接続待ち:%d - %d[msec]" ,icount , waittime) );
Sleep(waittime);
if ( IsConnected() == true ) {
int total_order;
int pos;
total_order = OrdersTotal();
for ( pos = 0 ; pos < total_order ; pos++ ) {
if ( OrderSelect( pos , SELECT_BY_POS ) == true ) {
if ( OrderMagicNumber() != MAGIC_NO ) {
continue;
}
if ( OrderSymbol() != Symbol() ) {
continue;
}
if ( OrderType() != in_cmd ) {
continue;
}
tempret = OrderTicket();
break;
}
}
if ( tempret < 0 ) {
debug_print( __LINE__ , "対象ポジション情報無し" );
break;
}
}
if ( tempret > -1 ) {
break;
}
}
return tempret;
}
void debug_print( int in_line , string in_str ){
if ( Input_Debug == true ) {
printf("【%d】%s" , in_line , in_str);
}
}