Ответ
 
Опции темы
Старый 06.04.2012, 19:33   #141 (permalink)
Активный участник
 
Аватар для vadim2490
 
Регистрация: 08.07.2011
Сообщений: 232
Репутация: 126
vadim2490 vadim2490
Сказал(а) спасибо: 424
Поблагодарили 125 раз(а) в 56 сообщениях
Поинты: 6
Сообщение от Ugar Посмотреть сообщение
Не кто понимает, а кто хочет помочь во взломе.
Для взломов есть ветка больничка.
Писал во всех ветках по теме...всем наверное лени сказать. Если понимать язык тут без всяких сложностеи можно определить!Никто не помог.
vadim2490 вне форума   Ответить с цитированиемОтветить с цитированием  
Старый 06.04.2012, 19:37   #142 (permalink)
Активный участник
 
Аватар для hitkill
 
Регистрация: 17.01.2012
Сообщений: 50
Репутация: 67
hitkill
Сказал(а) спасибо: 46
Поблагодарили 66 раз(а) в 16 сообщениях
Поинты: 13
спасибо!
hitkill вне форума   Ответить с цитированиемОтветить с цитированием  
Старый 06.04.2012, 20:17   #143 (permalink)
Местный знаток
 
Аватар для Milord
 
Регистрация: 26.03.2011
Сообщений: 596
Репутация: 705
Milord - Milord - Milord - Milord - Milord - Milord - Milord -
Сказал(а) спасибо: 897
Поблагодарили 702 раз(а) в 192 сообщениях
Поинты: 547

По умолчанию Как ввести реверс ордеров?


Правильно ли я написал Revers?
если =0,то без реверса, при =1, с реверсом!
if (Revers==0)
{
OrderSend(Symbol(),OP_BUY,Lots,Ask,slippage,Ask-SL*Point,Ask+TP*Point,"",Magic,0,Aqua);
}
else
{
OrderSend(Symbol(),OP_SELL,Lots,Bid,slippage,Bid+S L*Point,Bid-TP*Point,"",Magic,0,Magenta);
}
if (Revers==0)
{
OrderSend(Symbol(),OP_SELL,Lots,Bid,slippage,Bid+S L*Point,Bid-TP*Point,"",Magic,0,Magenta);
}
else
{
OrderSend(Symbol(),OP_BUY,Lots,Ask,slippage,Ask-SL*Point,Ask+TP*Point,"",Magic,0,Aqua);
}
Milord вне форума   Ответить с цитированиемОтветить с цитированием  
Старый 06.04.2012, 20:21   #144 (permalink)
Элитный участник
 
Аватар для Ugar
 
Регистрация: 13.03.2009
Сообщений: 2,255
Репутация: 1963
Ugar Ugar Ugar Ugar Ugar Ugar Ugar Ugar Ugar Ugar Ugar
Сказал(а) спасибо: 349
Поблагодарили 1,892 раз(а) в 1,069 сообщениях
Поинты: 1276
Отправить сообщение для Ugar с помощью ICQ
Сообщение от vadim2490 Посмотреть сообщение
Писал во всех ветках по теме...всем наверное лени сказать. Если понимать язык тут без всяких сложностеи можно определить!Никто не помог.
Понимающих в языке много. Но вот желающих помочь не нашлось. Ничего удивительного. Кроме понимания и лени есть ещё этическая сторона. Некоторые программисты, я в том числе, не желают ломать чужой код, и помогать в этом не станут.
Есть конечно те кто, хоть чуть чуть понимает в языке программирования и без отягощения всякими там этическими нормами. Но и им никакого интереса нет помогать. Взломать советник это одно. Результатом может быть то что он сам сможет воспользоваться взломанным кодом.
А так получается всё равно что попросить медвежатника взломать сейф за спасибо. А содержимое себе забрать.

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
Глубокое понимание процессов помогает в работе, но сильно мешает в отдыхе.
http://forexsystems.ru/signaturepics/sigpic3798_1.gif
Чужие программы не переделываю!
Ugar на форуме   Ответить с цитированиемОтветить с цитированием  
Старый 06.04.2012, 20:26   #145 (permalink)
Элитный участник
 
Аватар для Ugar
 
Регистрация: 13.03.2009
Сообщений: 2,255
Репутация: 1963
Ugar Ugar Ugar Ugar Ugar Ugar Ugar Ugar Ugar Ugar Ugar
Сказал(а) спасибо: 349
Поблагодарили 1,892 раз(а) в 1,069 сообщениях
Поинты: 1276
Отправить сообщение для Ugar с помощью ICQ
Сообщение от Milord Посмотреть сообщение
Правильно ли я написал Revers?
если =0,то без реверса, при =1, с реверсом!
if (Revers==0)
{
OrderSend(Symbol(),OP_BUY,Lots,Ask,slippage,Ask-SL*Point,Ask+TP*Point,"",Magic,0,Aqua);
}
else
{
OrderSend(Symbol(),OP_SELL,Lots,Bid,slippage,Bid+S L*Point,Bid-TP*Point,"",Magic,0,Magenta);
}
if (Revers==0)
{
OrderSend(Symbol(),OP_SELL,Lots,Bid,slippage,Bid+S L*Point,Bid-TP*Point,"",Magic,0,Magenta);
}
else
{
OrderSend(Symbol(),OP_BUY,Lots,Ask,slippage,Ask-SL*Point,Ask+TP*Point,"",Magic,0,Aqua);
}
В принципе можно и так. Только буквально если 0, то без реверса, а если любое другое значение то реверс.

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
Глубокое понимание процессов помогает в работе, но сильно мешает в отдыхе.
http://forexsystems.ru/signaturepics/sigpic3798_1.gif
Чужие программы не переделываю!
Ugar на форуме   Ответить с цитированиемОтветить с цитированием  
Пользователь сказал cпасибо:
eevviill (07.04.2012)
Старый 06.04.2012, 20:39   #146 (permalink)
Активный участник
 
Аватар для vadim2490
 
Регистрация: 08.07.2011
Сообщений: 232
Репутация: 126
vadim2490 vadim2490
Сказал(а) спасибо: 424
Поблагодарили 125 раз(а) в 56 сообщениях
Поинты: 6
Сообщение от Ugar Посмотреть сообщение
Понимающих в языке много. Но вот желающих помочь не нашлось. Ничего удивительного. Кроме понимания и лени есть ещё этическая сторона. Некоторые программисты, я в том числе, не желают ломать чужой код, и помогать в этом не станут.
Есть конечно те кто, хоть чуть чуть понимает в языке программирования и без отягощения всякими там этическими нормами. Но и им никакого интереса нет помогать. Взломать советник это одно. Результатом может быть то что он сам сможет воспользоваться взломанным кодом.
А так получается всё равно что попросить медвежатника взломать сейф за спасибо. А содержимое себе забрать.
Всё понеатно! Не хототе отбирать хлеб у колег по цеху.Если бы ето был толковый сов то я заплатил за его взлом, а так ето очеренднои развод для набора реферов.
vadim2490 вне форума   Ответить с цитированиемОтветить с цитированием  
Старый 06.04.2012, 20:46   #147 (permalink)
Активный участник
 
Аватар для Nata_FX
 
Регистрация: 12.10.2011
Сообщений: 50
Репутация: 36
Nata_FX
Сказал(а) спасибо: 10
Поблагодарили 35 раз(а) в 23 сообщениях
Поинты: 4
Сообщение от vadim2490 Посмотреть сообщение
Всё понеатно! Не хототе отбирать хлеб у колег по цеху.Если бы ето был толковый сов то я заплатил за его взлом, а так ето очеренднои развод для набора реферов.
Если развод, зачем ломать?
Nata_FX на форуме   Ответить с цитированиемОтветить с цитированием  
Старый 06.04.2012, 21:20   #148 (permalink)
Активный участник
 
Аватар для vadim2490
 
Регистрация: 08.07.2011
Сообщений: 232
Репутация: 126
vadim2490 vadim2490
Сказал(а) спасибо: 424
Поблагодарили 125 раз(а) в 56 сообщениях
Поинты: 6
Сообщение от Nata_FX Посмотреть сообщение
Если развод, зачем ломать?
Хочу протестить его на демо.Принчыпиално не хочу регитса по рефералнои ссылке для получения ключя.
vadim2490 вне форума   Ответить с цитированиемОтветить с цитированием  
Старый 07.04.2012, 09:07   #149 (permalink)
Заблокирован
За второе место в конкурсе 

 
Аватар для eevviill
 
Регистрация: 30.07.2009
Сообщений: 5,474
Репутация: 9022
eevviill eevviill eevviill eevviill eevviill eevviill eevviill eevviill eevviill eevviill eevviill
Сказал(а) спасибо: 13,680
Поблагодарили 9,022 раз(а) в 3,179 сообщениях
Поинты: 1105
Отправить сообщение для eevviill с помощью Skype™
Сообщение от vadim2490 Посмотреть сообщение
Здрасвуите! Очень хочу понять как по этим строкам сова генерирует ключ. Посмотрите плс кто понимает.

int li_24;
if (Key == "пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅ" || Key == "") {
gi_380 = FALSE;
Print("пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅп їЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅ");
if (ObjectFind(gs_key_384) == -1) ObjectCreate(gs_key_384, OBJ_LABEL, 0, 0, 0);
ObjectSet(gs_key_384, OBJPROP_CORNER, 1);
ObjectSet(gs_key_384, OBJPROP_XDISTANCE, 5);
ObjectSet(gs_key_384, OBJPROP_YDISTANCE, 15);
ObjectSetText(gs_key_384, "пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅп їЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅ!", 10, "Tahoma", Red);
} else {
li_24 = StrToInteger(StringSubstr(Key, 0, StringLen(Key) - 2)) / gi_396 + 57;
gi_392 = StrToInteger(StringSubstr(Key, StringLen(Key) - 2, 2)) / StrToInteger(StringSubstr(Key, 0, 1));
if (AccountNumber() == li_24 || IsDemo() == TRUE || IsOptimization() == TRUE || IsTesting() == TRUE) {
gi_380 = TRUE;
Print("пїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅ!");
gs_key_384 = "label";
if (ObjectFind(gs_key_384) == -1) ObjectCreate(gs_key_384, OBJ_LABEL, 0, 0, 0);
ObjectSet(gs_key_384, OBJPROP_CORNER, 1);
ObjectSet(gs_key_384, OBJPROP_XDISTANCE, 5);
ObjectSet(gs_key_384, OBJPROP_YDISTANCE, 15);
ObjectSetText(gs_key_384, "пїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅ!", 10, "Tahoma", Lime);
MaxLots = 130.0 * Lots;
Там расчёт номера счёта. Если он совпадает, то торговля на реале разрешена.
Рекомендую всё удалить, кроме {MaxLots = 130.0 * Lots; и перед функцией start() добавить сточку bool gi_380 = TRUE;
eevviill вне форума   Ответить с цитированиемОтветить с цитированием  
Пользователь сказал cпасибо:
vadim2490 (07.04.2012)
Старый 07.04.2012, 10:03   #150 (permalink)
Местный знаток
 
Аватар для Milord
 
Регистрация: 26.03.2011
Сообщений: 596
Репутация: 705
Milord - Milord - Milord - Milord - Milord - Milord - Milord -
Сказал(а) спасибо: 897
Поблагодарили 702 раз(а) в 192 сообщениях
Поинты: 547

По умолчанию Можно ли еще упростить код реверса???


Сообщение от Ugar Посмотреть сообщение
В принципе можно и так. Только буквально если 0, то без реверса, а если любое другое значение то реверс.
как можно еще упростить мой вариант или свой предложите проще?
Milord вне форума   Ответить с цитированиемОтветить с цитированием  
Старый 07.04.2012, 12:26   #151 (permalink)
Элитный участник
 
Аватар для Ugar
 
Регистрация: 13.03.2009
Сообщений: 2,255
Репутация: 1963
Ugar Ugar Ugar Ugar Ugar Ugar Ugar Ugar Ugar Ugar Ugar
Сказал(а) спасибо: 349
Поблагодарили 1,892 раз(а) в 1,069 сообщениях
Поинты: 1276
Отправить сообщение для Ugar с помощью ICQ
Сообщение от Milord Посмотреть сообщение
как можно еще упростить мой вариант или свой предложите проще?
Пожалуй тот вариант был самый простой. Ещё вот такой вариант может быть:
Здесь в TypeOrder пишем OP_BUY для открытия Buy ордеров или OP_SELL для Sell ордеров.
double op, sl, tp,
color arrow;
int type, TypeOrder;
if ((Revers==0 && TypeOrder==OP_BUY) || (Revers==1 && TypeOrder==OP_SELL))
{
op=Ask;
sl=Ask-SL*Point;
tp=Ask+TP*Point;
arrow=Magenta;
type=OP_BUY;
}
else
{
op=Bid;
sl=Ask-SL*Point;
tp=Ask+TP*Point;
arrow=Magenta;
type=OP_SELL;
}
OrderSend(Symbol(),type,Lots,op,slippage,sl,tp,"", Magic,0,arrow);

Не знаю проще он или нет. Можно ещё вынести открытие в пользовательскую функцию, что бы не писать одно и то же 4 раза. Вообще, простота не не самое важное в коде, не стоит особо задумываться над этим.

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
Глубокое понимание процессов помогает в работе, но сильно мешает в отдыхе.
http://forexsystems.ru/signaturepics/sigpic3798_1.gif
Чужие программы не переделываю!

Последний раз редактировалось Ugar; 07.04.2012 в 12:31.
Ugar на форуме   Ответить с цитированиемОтветить с цитированием  
Старый 07.04.2012, 13:43   #152 (permalink)
Активный участник
 
Аватар для vadim2490
 
Регистрация: 08.07.2011
Сообщений: 232
Репутация: 126
vadim2490 vadim2490
Сказал(а) спасибо: 424
Поблагодарили 125 раз(а) в 56 сообщениях
Поинты: 6
Сообщение от eevviill Посмотреть сообщение
Там расчёт номера счёта. Если он совпадает, то торговля на реале разрешена.
Рекомендую всё удалить, кроме {MaxLots = 130.0 * Lots; и перед функцией start() добавить сточку bool gi_380 = TRUE;
Спосибо огромное за помошь! А какая там формула расчёта кюча?
vadim2490 вне форума   Ответить с цитированиемОтветить с цитированием  
Старый 07.04.2012, 17:28   #153 (permalink)
Заблокирован
За второе место в конкурсе 

 
Аватар для eevviill
 
Регистрация: 30.07.2009
Сообщений: 5,474
Репутация: 9022
eevviill eevviill eevviill eevviill eevviill eevviill eevviill eevviill eevviill eevviill eevviill
Сказал(а) спасибо: 13,680
Поблагодарили 9,022 раз(а) в 3,179 сообщениях
Поинты: 1105
Отправить сообщение для eevviill с помощью Skype™
Сообщение от vadim2490 Посмотреть сообщение
Спосибо огромное за помошь! А какая там формула расчёта кюча?
StrToInteger(StringSubstr(Key, 0, StringLen(Key) - 2)) / gi_396 + 57;
1)StrToInteger ==то что в скобках после этого будет округлено до целого числа. Например в скобках выйдет 6.4, то округлит и будет 6
2)StringSubstr отображает текстовую строку переменной. Имеет 3 параметра.
2.1)Key название переменной
2.2)0 позиция текста в переменной(если 0 то первое слово или сочетание цифр).
2.3)StringLen(Key) - 2 здесь указывается длина текста в переменной. В данном случае это StringLen вычисляет количество символов текста переменной Key а потом -2.
3) Ну а дальше это всё поделить на значение переменной gi_396(допустим 10) и +57.

Итак. Пример. Если Key="7654343"
2.3)7цифр-2=5
2.2)У нас одно сочетание цифр.
2.1)Key
2)Так как третий параметр 5, второй 0, первый Key, то значит что мы
из значения Key берём 1 сочетание цифр но только первые 5 цифр. А именно 76543.
1)Округляем до целого. Так и остаётся 76543.
3)Делим на переменную(её значение) gi_396(10) и плюсуем 57.
Вышло. 7707. Это число должно быть такое же на каком стоит советник для роботы на реале.
eevviill вне форума   Ответить с цитированиемОтветить с цитированием  
Пользователь сказал cпасибо:
vadim2490 (07.04.2012)
Старый 07.04.2012, 19:04   #154 (permalink)
Активный участник
 
Аватар для vadim2490
 
Регистрация: 08.07.2011
Сообщений: 232
Репутация: 126
vadim2490 vadim2490
Сказал(а) спасибо: 424
Поблагодарили 125 раз(а) в 56 сообщениях
Поинты: 6
Сообщение от eevviill Посмотреть сообщение
StrToInteger(StringSubstr(Key, 0, StringLen(Key) - 2)) / gi_396 + 57;
1)StrToInteger ==то что в скобках после этого будет округлено до целого числа. Например в скобках выйдет 6.4, то округлит и будет 6
2)StringSubstr отображает текстовую строку переменной. Имеет 3 параметра.
2.1)Key название переменной
2.2)0 позиция текста в переменной(если 0 то первое слово или сочетание цифр).
2.3)StringLen(Key) - 2 здесь указывается длина текста в переменной. В данном случае это StringLen вычисляет количество символов текста переменной Key а потом -2.
3) Ну а дальше это всё поделить на значение переменной gi_396(допустим 10) и +57.

Итак. Пример. Если Key="7654343"
2.3)7цифр-2=5
2.2)У нас одно сочетание цифр.
2.1)Key
2)Так как третий параметр 5, второй 0, первый Key, то значит что мы
из значения Key берём 1 сочетание цифр но только первые 5 цифр. А именно 76543.
1)Округляем до целого. Так и остаётся 76543.
3)Делим на переменную(её значение) gi_396(10) и плюсуем 57.
Вышло. 7707. Это число должно быть такое же на каком стоит советник для роботы на реале.
Спасибо! Вы так всё ясно поиснили,прям как в школе.
vadim2490 вне форума   Ответить с цитированиемОтветить с цитированием  
Пользователь сказал cпасибо:
eevviill (07.04.2012)
Старый 07.04.2012, 21:10   #155 (permalink)
Местный знаток
 
Аватар для Milord
 
Регистрация: 26.03.2011
Сообщений: 596
Репутация: 705
Milord - Milord - Milord - Milord - Milord - Milord - Milord -
Сказал(а) спасибо: 897
Поблагодарили 702 раз(а) в 192 сообщениях
Поинты: 547

По умолчанию А где ваша сова для лома?))


Сообщение от vadim2490 Посмотреть сообщение
Хочу протестить его на демо.Принчыпиално не хочу регитса по рефералнои ссылке для получения ключя.
Киньте вашу сову, думаю если не я,так кто нить ее вскроет))
Milord вне форума   Ответить с цитированиемОтветить с цитированием  
Старый 07.04.2012, 21:16   #156 (permalink)
Местный знаток
 
Аватар для Milord
 
Регистрация: 26.03.2011
Сообщений: 596
Репутация: 705
Milord - Milord - Milord - Milord - Milord - Milord - Milord -
Сказал(а) спасибо: 897
Поблагодарили 702 раз(а) в 192 сообщениях
Поинты: 547

По умолчанию Спасибо Ugar!)


Сообщение от Ugar Посмотреть сообщение
Пожалуй тот вариант был самый простой. Ещё вот такой вариант может быть..............
.........Не знаю проще он или нет. Можно ещё вынести открытие в пользовательскую функцию, что бы не писать одно и то же 4 раза. Вообще, простота не не самое важное в коде, не стоит особо задумываться над этим.
После опыта программирования на бейсике десятков программ, убедился, что чем проще и меньше код, тем он быстрее выполняется компьютером, быстрее компилируется, и вообще его проще читать!)
сравните код советника на MQL4, который умещается на экране, без скроллинга, и другой, который листать устанешь
Milord вне форума   Ответить с цитированиемОтветить с цитированием  
Старый 07.04.2012, 22:40   #157 (permalink)
Активный участник
 
Аватар для vadim2490
 
Регистрация: 08.07.2011
Сообщений: 232
Репутация: 126
vadim2490 vadim2490
Сказал(а) спасибо: 424
Поблагодарили 125 раз(а) в 56 сообщениях
Поинты: 6
Сообщение от Milord Посмотреть сообщение
Киньте вашу сову, думаю если не я,так кто нить ее вскроет))
Сову я давно уже вскрыл через ex4tomq4.net после прочтения кода понял что заплатил зря 3$ на вскрырие так как советник был клоном турбопрофита.
vadim2490 вне форума   Ответить с цитированиемОтветить с цитированием  
Старый 08.04.2012, 07:10   #158 (permalink)
Элитный участник
 
Аватар для Ugar
 
Регистрация: 13.03.2009
Сообщений: 2,255
Репутация: 1963
Ugar Ugar Ugar Ugar Ugar Ugar Ugar Ugar Ugar Ugar Ugar
Сказал(а) спасибо: 349
Поблагодарили 1,892 раз(а) в 1,069 сообщениях
Поинты: 1276
Отправить сообщение для Ugar с помощью ICQ
Сообщение от Milord Посмотреть сообщение
После опыта программирования на бейсике десятков программ, убедился, что чем проще и меньше код, тем он быстрее выполняется компьютером, быстрее компилируется, и вообще его проще читать!)
сравните код советника на MQL4, который умещается на экране, без скроллинга, и другой, который листать устанешь
Скорость компиляции вообще не имеет значения, если мне придётся подождать компиляцию не 1, а 3 секунды, ничего страшного.
Длинный текст неудобно читать, но текст программы это же не роман или детектив. Кстати не факт что весь текст в работе. У меня есть функция 300 строк, вызывается она редко и используется из неё всего пару строк, но вот какие именно зависит от ситуации. Так что её длинна на скорость не влияет.
Скорость работы конечно важно, но надёжность важнее. И не всегда чем короче текст, тем быстрее работает. Иногда для ускорения работы приходится немного увеличивать текст.

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
Глубокое понимание процессов помогает в работе, но сильно мешает в отдыхе.
http://forexsystems.ru/signaturepics/sigpic3798_1.gif
Чужие программы не переделываю!
Ugar на форуме   Ответить с цитированиемОтветить с цитированием  
Старый 09.04.2012, 09:24   #159 (permalink)
Интересующийся
 
Аватар для Selhal
 
Регистрация: 16.11.2010
Сообщений: 3
Репутация: 1
Selhal
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Поинты: 0
Помогите вставить правильно трал в советник.Я не програмер вставил трал но он не работает
Вложения:
Тип файла: mq4 e-TFL_v2.mq4 (32.5 Кб, 14 просмотров)
Тип файла: mq4 ttttttttt.mq4 (33.6 Кб, 17 просмотров)
Selhal вне форума   Ответить с цитированиемОтветить с цитированием  
Старый 10.04.2012, 12:42   #160 (permalink)
Прохожий
 
Аватар для vet666
 
Регистрация: 10.04.2012
Сообщений: 1
Репутация: 1
vet666
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Поинты: 0
подскажите плс действие сравнения

если а+б
и с+д


то Алерт.....

, спасиб!
vet666 вне форума   Ответить с цитированиемОтветить с цитированием  
Ответ

Метки
mql4, mql4 помощь, вопросы mql4


Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Trackbacks are Выкл.
Pingbacks are Выкл.
Refbacks are Выкл.



Текущее время: 22:01. Часовой пояс GMT.


Перевод: zCarot
Copyright ©2000 - 2016, Jelsoft Enterprises Ltd.
SEO by vBSEO