voidOnTick(){
//--- объявление и инициализация запроса и результатаMqlTradeRequest request={0};
MqlTradeResult result={0};
//--- параметры запроса
request.action =TRADE_ACTION_DEAL; // тип торговой операции
request.symbol =Symbol(); // символ
request.volume =0.1; // объем в 0.1 лот
request.type =ORDER_TYPE_BUY; // тип ордера
request.price =SymbolInfoDouble(Symbol(),SYMBOL_ASK); // цена для открытия
request.deviation=5; // допустимое отклонение от цены
request.magic =EXPERT_MAGIC; // MagicNumber ордера//--- отправка запросаif(!OrderSend(request,result))
PrintFormat("OrderSend error %d",GetLastError()); // если отправить запрос не удалось, вывести код ошибкиAlert(GetLastError());
//--- информация об операцииPrintFormat("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order);
}
とこちらも
uint SendRandomPendingOrder(longconst magic_number)
{
//--- готовим запрос MqlTradeRequest request={0};
request.action=TRADE_ACTION_PENDING; // установка отложенного ордера
request.magic=magic_number; // ORDER_MAGIC
request.symbol=_Symbol; // инструмент
request.volume=0.1; // объем в 0.1 лот
request.sl=0; // Stop Loss не указан
request.tp=0; // Take Profit не указан //--- сформируем тип ордера
request.type=GetRandomType(); // тип ордера //---сформируем цену для отложенного ордера
request.price=GetRandomPrice(request.type); // цена для открытия //--- отправим торговый приказ MqlTradeResult result={0};
OrderSend(request,result);
//--- выведем в лог ответ сервера Print(__FUNCTION__,":",result.comment);
if(result.retcode==10016) Print(result.bid,result.ask,result.price);
//--- вернем код ответа торгового сервера return result.retcode;
}
// Функция ищет бар, внутри которого находится указанный момент.
// Если такой бар найден - возвращается true и ссылка rIdx устанавливает нужное значение
// Если такой бар не найден - возвращается false и ссылка rIdx устанавливает значение на ближайший индекс,
// время которого меньше, требуемого.
// При недостаточности буффера функция возвращает false, ссылка устанавливается на отрицательное значение.
// NOTE !!! ненаступивший момент может лежать внутри нулевого бара, в этом случае вернется true,
// даже если фактически данный момент еще не наступил. false вернется только если данный момент лежит позже
// нулевого бара.
// Если искомый момент находится раньше самого раннего бара, возвращается false и rIdx = INT_MAX
bool CTSTime::FindIdxOf(datetime dtMomentToFind,int& rIdx)
{
ASSERT(dtMomentToFind > MIN_DATETIME && dtMomentToFind < NEVER_EXPIRES);
// Пока найденный индекс - невалиден.
rIdx = WRONG_VALUE;
// Если данных нет - возвращаем отрицательный результат поиска.if(GetTSSize() == 0)
return(false);
// Найдем продолжительность текущего бараint iSecondsInBar = PeriodSeconds(m_etTimeframe);
ASSERT(iSecondsInBar >= SECS_IN_MINUTE);
datetime dtMomentOfZeroBar = GetTime(0);
datetime dtMomentOfLastBar = GetTime(GetTSSize()-1);
// Искомый момент лежит внутри или позже, чем нулевой бар ? if(dtMomentToFind >= dtMomentOfZeroBar)
{
rIdx = 0;
// Искомый момент лежит на открытии минус первого бара или позже ? if(dtMomentToFind >= dtMomentOfZeroBar + iSecondsInBar)
return (false); // Искомый момент лежит после нулевого бара. // Искомый момент лежит внутри нулевого бара.return(true);
};
// Здесь ясно, что искомый момент был ранее нулевого бара. // Проверим, может быть искомый момент лежит раньше последнего бара ? if(dtMomentToFind < dtMomentOfLastBar)
{
// Увы, такого раннего момента в таймсерии нет. // Возвращаем самый большой индекс бара, какой можем возвратить// (Потому, что бара со временем меньше требуемого - в таймсерии нет).
rIdx = INT_MAX;
return(false);
};
// Здесь ясно, что искомый момент был позже начала самого раннего бара, но раньше начала самого нового бара.
ASSERT(GetTSSize() > 1); // Проверим, размер буффера должен быть минимум два бара. (Иначе условие не выполняется, что искомый момент был позже начала самого раннего бара, но раньше начала самого нового бара, не выполняется)// Ищем примерно, где был данный момент.
ASSERT(dtMomentOfZeroBar > dtMomentToFind);
ASSERT(dtMomentOfZeroBar > dtMomentOfLastBar);
ulong ulSecFromSearchToLatest = dtMomentOfZeroBar - dtMomentToFind;
ulong ulSecFromEarlestToLatest = dtMomentOfZeroBar - dtMomentOfLastBar;
ASSERT(ulSecFromEarlestToLatest > ulSecFromSearchToLatest);
double dResIdx = (double)ulSecFromSearchToLatest*(double)(GetTSSize()-1)/(double)ulSecFromEarlestToLatest;
ASSERT(dResIdx <INT_MAX && dResIdx >= 0);
int iResIdx = (int)MathRound(dResIdx);
ASSERT(iResIdx >= 0 && iResIdx<(int)GetTSSize()); // По идее, мы должны уложиться в этот диапазон.// Поскольку мы исследуем минимум два бара (текущий и следующий),// Текущий бар не должен быть нулевым.// Поскольку случай с буффером в один бар у нас был отсеян раньше, мы не должны получить ошибку.if(iResIdx == 0)
iResIdx = 1;
// Получен приблизительный индекс (uiResIdx).// Уточняем. Берем два бара, текущий и следующий.datetime dtResMoment;
datetime dtNextMoment;
dtResMoment = GetTime(iResIdx);
dtNextMoment = GetTime(iResIdx-1);
int iShift = 0;
bool bUp = false;
bool bDown = false;
do
{
if(dtResMoment > dtMomentToFind) // Если искомый момент раньше начала первого бара
{
iShift = 1; // Возьмем на один бар раньше.
bUp = true; // Запомним направление
}
else// Иначе - Искомый момент равен или позже начала первого бара.
{
if(dtNextMoment <= dtMomentToFind) // Если искомый момент больше или равен началу второго бара
{
iShift = -1; // Возьмем на один бар позже
bDown = true; // Запомним направление
}
else// Иначе - искомый момент равен или позже начала перого бара и раньше начала второго бара
{
iShift = 0; // То есть, можно выходить из цикла коррекции.
}
}
iResIdx += iShift; // Смещаемсяif(iResIdx > (int)GetTSSize() || iResIdx <= 0) // Проверим на допустимый диапазон
{
ASSERT(false); // В серии недостаточно данных (мал буффер)
rIdx = INT_MAX;
return(false);
};
dtResMoment = GetTime(iResIdx); // Запрашиваем новые данные
dtNextMoment = GetTime(iResIdx-1);
if(bUp == true && bDown == true) // Контроль направления коррекции
{
ASSERT(false); // Сменилось направление коррекции !!!
iShift = 0;
}
}
while(iShift != 0);
// В этой точке искомый момент равен или позже начала перого бара и раньше начала второго бара.// Проверим, может быть, искомый момент позже конца первого бара, но раньше начала второго бара // (между барами разрыв, и искомый момент находится именно там)// Ясно, что ссылка должна показывать на первый бар в любом случае
rIdx = iResIdx;
if(dtMomentToFind >= dtResMoment+iSecondsInBar)
// Действительно, искомый момент - внутри разрыва между барами.return(false);
return(true);
};
C言語を学ぶ前に、プログラマーがマシンコマンド、アセンブラ、Fortran、PL/1、Pascalやその他多くのものを経て、教科書もなく、適切な説明もなく、Volchanskyが上で述べたように、曲がった文字で印刷されたドキュメントで学んだ時代は、もう長くはないでしょう。
そして、この言語の課題は、アプリケーションの利用者が、プログラミングを深く掘り下げることなく、この端末言語を素早く習得して利用できるようにすることである。
同感です!それはいい指摘ですね。取引端末は、取引を容易にするものでなければならない。
誰で判断しているのですか?会社の顔として、荒らしにすり寄るのはよろしくない。MT4の経験者でも苦労していると既に書かれていますね。そして、彼らはそれを必要としない。
荒らしが見えるか?
すでに何度も書いていますが、ストラテジーのテストEAをシンプルかつ簡単に書く機会はいくらでもあります。
ヘルプのリンクも貼った。でも、ヘルプに関する質問をするようになれば、「こういう知識に興味があるんだ」とわかるはずです。でも、何もかもが悪いということが延々と続いていたんです。
だから、今の世代は、18歳で車を買って、21歳で家を買って、という世代なのかもしれません。でも、勉強するには......いや、なぜ?
アセンブラはどの程度複雑なのでしょうか?
というのも、ほんの10年前までは、初心者はこのフォーラムでもっと複雑で興味深い質問をしていたのです。
ちなみに、今日のMQL4の問題は、MQL5よりずっと情報量が多いですね。理由は明白で、MQL-versionsの時代ではありません。
いいえ、そうではありません。どういうことですか?
アレクセイ、本当に、今、例を挙げることはできないんだ。しかし、あなたは実験が好きなのですね。実行し、異なる入力データで何が返ってくるか見てみましょう。
ただ、今思い出して探すのは難しいですね。
さて、fxsaberさんが例を挙げてくれましたので(私用に修正しました)、コードを比較してみてください。
ここでは、どのような条件でBars()がファウルを返すかを見ることができます。
初心者が最初に書くのは、トレーディングスクリプトです。2つ目は、シンプルな指標です。3つ目は、シンプルなExpert Advisorです。
MQL4の最初のステージでさえ、MQL5より高速です。
トレーディングスクリプト?Expert AdvisorやStandard Libraryの 代わりになるものはないのでしょうか?
私の考えでは、トレーディングスクリプトを書くことは、明らかに中級者向けの作業であり、決して初心者には向いていません。
初心者は、まず一番簡単なライン出力に限ります。続いて-シンプルなインジケーターです。そして初めて、インジケーターや取引機能のリクエストに移ります。
アセンブラはどの程度複雑なのか、機能を教えてほしい。
どんな機能?
アセンブラは、「その関数が必要」というには特殊すぎるのです。
SBがフォーラムで初心者に何を売っているのか、なぜlazybonesから遠い人でも本当に苦労しているのか、というテーマで新鮮な例を挙げています。今日、MQL5について、愚痴をこぼすことなく、非常に建設的な質問をいただきました。
トレーディング、自動売買システム、トレーディング戦略のテストに関するフォーラムです。
バグ、バグ、質問
ダミルカ さん 2018.01.09 12:14
こんにちは!https://www.mql5.com/ru/articles/100 からMQL5の勉強を始めました。コードを起動したら、エラー4756が発生しました。まずは簡単なもの(Alert/Print...)から始めてみようと思ったのです。最も重要な機能のひとつがOrderSendです。OrderSendの使い方について、フォーラム/ドキュメントを検索し始めました。この記事https://www.mql5.com/ru/docs/constants/tradingconstants/enum_trade_request_actions、 買いポジションを開くためのコードが見つかりました。エラー4756とretcode10030が出ました。10030 - それはOrderSendプロパティであることは理解しましたが、このプロパティがどのように使用されるべきか(他の人のコードを見ました)、主に何のために使用されるのかが理解できていません。その後、https://www.mql5.com/ru/docs/trading/ordersend を開き、 コードをコピーして起動したところ、すべてうまくいきました。
しかし、なぜエラー4756が出るのか、どうすれば10030と同じように解消できるのか、まだ理解できていません。
の間のコードを見てみました。
とこちらも
私にはほとんど同じに見えますが、これらのエラーが表示される場所(4756と10030)は見えません。指をさして説明してください。
司会者回答
トレーディング、自動売買システム、ストラテジーテスターに関するフォーラム
エラー、バグ、質問
ウラジミール・カルプトフ さん 2018.01.09 12:20
CTradeのトレードクラスを使用することで、間違いをできるだけ少なくすることができます。
買いを開くための取引注文を送信する例。
おそらく、整理するのに役立ったのでしょう。しかし、実はこのルーキーには、とても深刻な問題があるのです。
トレーディング、自動売買システム、ストラテジーテストに関するフォーラム
バグ、バグ、質問
fxsaber さん 2018.01.09 13:22
https://www.mql5.com/ru/search#!keyword=Unsupported%20filling%20mode
つまり、指定されたトピックのリンクを読みに行く必要があるのです。SBでは、これを素晴らしい場を通じて解決しています。つまり、最もシンプルなトレーディングスクリプト(初心者が最初に使うプログラム)を書くのは、ほとんど簡単なことなのです。
トレードスクリプト ?Expert Advisorや、Standard Libraryの 代わりになるものはないのでしょうか?
私の考えでは、トレードスクリプトを書くのは明確な中級者向けの作業であり、初心者には決して向いていません。
初心者は、まず一番簡単なライン出力に限ります。続いて-シンプルなインジケーターです。そして初めて、インジケーターや取引機能のリクエストに移ります。
早速、多通貨MTF Expert Advisorを使い始めました。そして、新人のブランチでもいい感じでした。そして、あまり多くの質問をしなかったのは、どこかにヘルプと脳みそがあるから・・・。
あ、iBarsShiftと いえば。
以下は私の対になる関数です(CTSTimeは時系列クラス)、コメントを入れても初心者にはちょっと複雑だと思います。だから、SBには本当に欠けているんです。