fbpx

คำถามจากการใช้สูตร AFL ของห้องทดลองครับ???

SiamQuant Minimal Home – White Webboard ห้องโปร : Professional Membership Support คำถามจากการใช้สูตร AFL ของห้องทดลองครับ???

  • ผู้สร้าง
    กระทู้
  • #10169
    chaipod
    Participant

    1. ถ้าเปลี่ยนวัน Rotation จากวันสุดท้ายของเดือนเป็นวันแรกของเดือน
    แล้วทำไมไม่มีการ trade ครับ???

    อย่างเช่น 52-Week High AFL หรืออื่นๆ
    ถ้าแก้ไขสูตร 2 จุดคือ และอย่างอื่นเหมือนเดิม

    firstDayofMonth  = Month() != Ref( Month(), -1 );
    firstDayofYear  = Year() != Ref( Year(), -1 );
    PositionScore = IIf( firstDayofYear, Score, scoreNoRotate );

    พอ backtest แล้วจะไม่มี result ออกมา
    แสดงว่าเราต้อง rotation ได้เฉพาะวันสุดท้ายของเดือนเท่านั้น
    หรือตามเวลาที่ siamquant กำหนดไว้ในสูตรแค่นั้นเหรอครับ
    ถ้าต้องการกำหนดเวลา rotation ที่ต่างออกไปต้องทำยังไงครับ???

    2. slippage ไม่มีผลกับระบบ rotation หรือครับ???
    ลองแก้ไขดังนี้:

    //Trade Range Proportional Slippage
    EntrySlip    = 0.25;
    ExitSlip    = 0.25;

    ผลการ backtest แบบ slippage=0 และ slippage=0.25 จะเหมือนกันครับ

    3. ลำดับทีหายไปเกิดจากอะไรครับ???
    จากสูตร Magic Formula AFL
    ทำ explore เพื่อดูลำดับของ RankROCR กับ RankEY วันสุดท้ายข้องปี 2015
    จากรูป จะเห็นว่าลำดับของ RankEY เรียงตามปกติ
    แต่ลำดับของ RankROCR จะกระโดดและมีลำดับหายไปมาก
    เกิดจากอะไรครับ???

กำลังดู 10 ข้อความตอบกลับ - 1 ผ่านทาง 10 (ของทั้งหมด 10)
  • ผู้เขียน
    ข้อความตอบกลับ
  • #10170
    chaipod
    Participant

    RankEY

     

    #10172
    chaipod
    Participant

    RankROCR

    #10179
    BlueStepz
    Participant

    สวัสดีครับคุณ chaipod

    ขอบคุณสำหรับคำถามนะครับ 😀

    ถ้าอย่างนั้นขออนุญาตตอบคุณ chaipod เป็นข้อๆไปนะครับ

     

    1.  ในการทดสอบระบบ Rotation บน Amibroker มันมักจะมีจุดที่ต้องระวังนิดหน่อยครับ

    สาเหตุที่คุณ chaipod ทดสอบแล้วไม่มีผลการเทรดออกมา

    คาดว่าปัญหาน่าจะเกิดจากการกำหนด TradeDelay ครับ

    หากคุณ chaipod ต้องการเปลี่ยน Rotational Timing ที่นอกหนือไปจากสูตรที่ทางทีมงานกำหนดให้

    ให้คุณ chaipod ลบสูตรในส่วนของ Order Execution & Slippage ออกให้หมดก่อนครับ

    /*==================================================
    Order Execution & Slippage
    ==================================================*/

    //Trade Delays
    Buydl = 1;
    Selldl = 1;
    Shortdl = 1;
    Coverdl = 1;
    SetTradeDelays( Buydl, Selldl, Shortdl, Coverdl );

    //Trade Range Proportional Slippage
    EntrySlip = 0.00;
    ExitSlip = 0.00;
    BuyPrice = O + ( ( H – O ) * EntrySlip );
    SellPrice = O + ( ( L – O ) * ExitSlip );

    แล้วเปลี่ยนค่า TradeDelay = 0 เป็นค่า Default ตามรูปเลยครับ

    จากนั้นลองเปลี่ยนสูตร Rotational Timing ได้ตามต้องการเลยครับ

    ในตัวอย่างนี้ผมลองเปลี่ยนเป็น FirstDayofYear ได้ผลลัพธ์ออกมาตามรูปนี้ครับ

    ประเด็นตรงนี้ต้องขออธิบายก่อนว่าการใช้ระบบ Rotational เป็นเหมือน Mode พิเศษใน Amibroker

    ซึ่งดูแล้วเหมือนเป็นเด็กที่ค่อนข้างเอาแต่ใจเลยทีเดียวครับ

    กล่าวคือ Algorithm หลังบ้านถูกออกแบบมากไม่ยืดหยุ่นมากนัก

    และมักจะกำหนดให้ใช้ค่า Default มากกว่าเพื่อป้องกันผลลัพธ์ของการทดสอบที่อาจจะคาดเคลื่อนได้ครับ

    ยกตัวอย่างเช่น

    • การกำหนด TradePrice และ TradeDelay จะใช้ BuyPrice และ BuyDelay เป็นตัวแทนของทั้งหมด ไม่ว่าจะเป็น Entry/Exit หรือ Long/Short ก็ตาม ดังนั้น SellPrice/ShortPrice/CoverPrice และ SellDelay/ShortDelay/CoverDelay จึงไม่มีนัยยะอะไรใน Mode นี้
    • การกำหนด BuyPrice/BuyDelay ไม่สามารถเขียนคำสั่งผ่าน AFL เพื่อทำการ Overwrite สูตรได้โดยตรง ดังนั้นหากต้องการเปลี่ยนค่า BuyPrice/BuyDelay เราจึงต้องวิ่งไปกดเปลี่ยนในหน้า Bactester Setting เอาเอง
    • และในเมื่อไม่สามารถเขียนคำสั่ง BuyPrice บน AFL ได้ เราจึงเขียน Slippage เข้าไปตรงๆไม่ได้เช่นเดียวกัน

    อ้างอิง https://www.amibroker.com/guide/afl/enablerotationaltrading.html

    ปล. จากการทดสอบหลายๆครั้งพบว่าเราสามารถแอบเขียน TradeDelay ได้อย่างหนึ่งครับ 😀

    แต่ในทางที่ดีหากต้องการปรับสูตร Rotational จริงๆนอกเหนือจากที่ทีมงานกำหนดไว้ให้เป็น Template กว้างๆ

    ให้ทำเข้าไปปรับในหน้า Backtester Setting ตามวิธีที่กล่าวไว้ข้างต้นจะดีกว่าครับ

    #10182
    BlueStepz
    Participant

    2. ตามที่อธิบายคุณ chaipod ไปในข้อที่ 1 ครับ

    เนื่องจาก Rotational Mode ไม่สามารถเขียน BuyPrice ใน AFL ได้

    ต้องกำหนดเอาในหน้า Backtester Setting เท่านั้น

    ทำให้ไม่สามารถเขียน Slippage ผ่าน BuyPrice ได้ตรงๆเช่นเดียวกันครับ

    สำหรับการแก้ปัญหาเบื้องต้นอาจจะกำหนด BuyPrice ให้เป็น Field อื่น

    เช่น BuyPrice = High หรือ BuyPrice = Average เป็นต้น แทนค่า Default ที่เป็นค่า Close ครับ

    #10185
    BlueStepz
    Participant

    3. ในเรื่องของการ Ranking แล้วพบว่าลำดับของหุ้นหายไป

    ขออธิบายคุณ chaipod แบบนี้นะครับ

    ลำดับของหุ้นที่หายไปคือ ลำดับของหุ้นที่ไม่มีข้อมูลในวันนั้นครับ

    ตัวอย่างเช่น ถ้าเรียงลำดับตาม ROCR Rank จากน้อยไปหามาก จากการ Explore สูตรในวันที่ 2015-12-30 (YMD)

    จะพบว่าหุ้น SSI มี Rank=2 และหุ้น ADVANC มี Rank=10 เป็นต้น

     

    หากต้องการหารายชื่อหุ้นที่หายไปว่าคือหุ้นตัวไหน เราสามารถตรวจสอบเบื้องต้นได้

    โดยการติ๊กที่ช่อง Pad and align all data to reference symbol: ในหน้า Backtester Setting

    และเลือก ^SET เป็น symbol ที่ใช้ในการอ้างอิงครับ

    จากนั้นให้ Explore สูตรใหม่อีกครั้งจะพบรายชื่อหุ้นของลำดับ ROCR ที่หายไป ตามรูปประกอบด้านล่างนี้ครับ

    ปัญหาดังกล่าวเกิดจากการใช้ Ranking Feature ของ Amibroker ตามคำสั่งในส่วนนี้ครับ

    wlnum = CategoryFind( “ALLSTOCK”, categoryWatchlist );
    symlist = CategoryGetSymbols( categoryWatchlist, wlnum );

    if( Status(“stocknum”) == 0 )
    {

    for( i = 0; ( sym = StrExtract( symlist, i ) ) != “”; i++ )
    {
    MKC = Foreign( sym + “-SQ1”, “V” );


    ROCR = Nz( EBIT / ( TA – TCL ) );
    EY = Nz( EBIT / ( MKC + TL – TC ) );

    StaticVarSet( “ROCRScore” + sym, ROCR );
    StaticVarSet( “EYScore” + sym, EY );
    }

    StaticVarGenerateRanks( “Rank”, “ROCRScore”, 0, 1224 );
    StaticVarGenerateRanks( “Rank”, “EYScore”, 0, 1224 );
    }

    จะเห็นได้ว่าเงื่อนไขใน For-Loop จะเป็นการกำหนดค่า ROCR และ EY แบบ Array ตามรายชื่อของหุ้นไปทีละตัว

    ไม่ได้กำหนดเงื่อนไขเจาะลึกลงไปถึงแต่ละ Bar ใน Array Index เหมือนคำสั่ง for( i = 0; i < BarCount; i++ )

    ทำให้คำสั่ง StaticVarSet เก็บค่า ROCR และ EY ของหุ้นทุกตัวของ Array ทุกช่องที่ความยาวข้อมูลเท่าๆกัน

    โดยความยาวข้อมูลจะอ้างอิงตามหุ้นตัวแรกที่ถูกคำนวณ ซึ่งในที่นี้คือหุ้น “0SET”

    หากช่อง Array ไหนที่หุ้นไม่มีข้อมูล โปรแกรมจะดึงข้อมูลจากช่อง Array ก่อนหน้ามาเติมให้

    เสมือนกับการกดติ๊กเลือก Pad and Align… นั่นเองครับ

    เพื่อให้เข้าใจง่าย ทางทีมงานเลยทำภาพประกอบให้เห็นภาพมากขึ้น

    จากภาพหุ้นที่ถูกคำนวณเป็นตัวแรกที่ใช้อ้างอิงคือ หุ้น “0SET” เป็นหุ้นที่ถูกสร้างขึ้นมาเพื่อจำลองข้อมูลของ SET Index ทั้งหมด

    ( เหตุผลเนื่องจากว่าถ้าหากไม่มีหุุ้น “0SET” ใน Universe ของเรา เมื่อเราใช้การ Ranking

    โปรแกรมจะทำการ Ranking ตามช่วงเวลา/ตามความยาวของข้อมูลหุ้นตัวแรกเรียงตามตัวอักษร

    ทำให้เราได้หุ้นอ้างอิงคือหุ้น “2S” ส่งผลให้ระบบจะถูกทดสอบเริ่มตั้งแต่ปี 2009 ตามข้อมูลของหุ้น “2S” )

    สมมติว่าหุ้นอ้างอิง “0SET” มีความยาวข้อมูล 5 ช่องตั้งแต่ Array Index[0] ถึง Array Index[4]

    แต่หุ้น A มีความยาวข้อมูลเพียงแค่ 3 ช่องคือ Array Index[0] ถึง Array Index[2]

    ดังนั้นเมื่อใช้การ Ranking โปรแกรม Amibroker จะทำการเติมข้อมูลของหุ้น A

    โดยข้อมูลในช่อง Array Index[3] และจะถูกดึงจากข้อมูลในช่อง Array Index[2]

    และข้อมูลในช่อง Array Index[4] และจะถูกดึงจากข้อมูลในช่อง Array Index[3] ตามลำดับ

    ซึ่งเป็นผลมาจากการใช้ For-Loop : for( i = 0; ( sym = StrExtract( symlist, i ) ) != “”; i++ ) ใน Ranking Feature นี้นั่นเองครับ

    อ้างอิง: https://www.amibroker.com/guide/h_ranking.html

     

    แนวทางในการแก้ปัญหาเบื้องต้น

    หากต้องการ Explore รายชื่อหุ้นหรือค่าต่างๆจากการ Ranking

    เราอาจจะต้องทำการสร้าง Wachlist ใหม่ที่ประกอบไปด้วย

    รายชื่อของหุ้นที่ยัง Active หรือมีข้อมูลอยู่ในวันที่เราต้องการจะ Explore เหมือนกัน

    ซึ่งจะทำให้เวลาใช้การ Ranking โปรแกรม Amibroker จะได้ไม่ต้องทำการเติมข้อมูลใหม่ให้ครับ

    เริ่มต้นด้วยการ Explore หาหุ้นที่ยัง Active เพื่อนำรายชื่อหุ้นมาสร้าง Watchlist ใหม่ตามวิธีต่อไปนี้ครับ

    1. สร้างไฟล์ AFL และเขียนคำสั่งตามสูตรนี้ครับ

    SQMKC = Foreign( Name() + “-SQ1”, “V” );
    SQTA = Foreign( Name() + “-SQ4”, “O” );
    SQTCL = Foreign( Name() + “-SQ4”, “V” );
    SQTL    = Foreign( Name() + “-SQ4”, “H” );
    SQTC = Foreign( Name() + “-SQ4”, “L” );
    SQEBIT = Foreign( Name() + “-SQ5”, “H” );

    Filter = 1;
    AddColumn( C, “Close”, 1.2 );
    AddColumn( SQMKC, “SQMKC”, 1.2 );
    AddColumn( SQTA, “SQTA”, 1.2 );
    AddColumn( SQTCL, “SQTCL”, 1.2 );
    AddColumn( SQTL, “SQTL”, 1.2 );
    AddColumn( SQTC, “SQTC”, 1.2 );
    AddColumn( SQEBIT, “SQEBIT”, 1.2 );

    2. เลือก Filter คือ Watchlist ALLSTOCK และ Range ในการ Explore แบบ From-To dates และวันที่ 2015-12-30 (YMD)

    3. อย่าลืมว่าเราไม่เอาติ๊กหน้าช่อง Pad and align นะครับ ตรวจสอบเรียบร้อยแล้วกดปุ่ม Explore ได้เลย!

    4. หลังจากได้รายชื่อหุ้นที่ Active ในวันที่เราต้องการจะ Explore ออกมาแล้ว ให้เราคลิกขวาและเลือก Add all results to watchlist…

    5. ในตัวอย่างนี้เราจะเอารายชื่อหุ้นที่ Active ในวันที่ 2015-12-30 (YMD) ไปไว้ใน Watchlist ที่ชื่อว่า “ACTIVESTOCK20151230”

     

    6. จากนั้นกลับไปที่สูตร Explore Magic Formula เปลี่ยนคำสั่งที่ใช้ในการเลือก Watchlist จาก “ALLSTOCK” เป็น “ACTIVESTOCK20151230” แทน

    wlnum = CategoryFind( “ACTIVESTOCK20151230”, categoryWatchlist );
    symlist = CategoryGetSymbols( categoryWatchlist, wlnum );

     

    7. จากนั้นกดปุ่ม Explore จากสูตร Magic Formula เราก็จะได้รายชื่อหุ้นที่มีการเรียงลำดับถูกต้องตามค่า ROCR และ EY นั่นเองครับ

    Ranking ROCR : 2015-12-30

    Ranking EY : 2015-12-30

    ท้ายสุดแต่ไม่สุดท้าย

    สำหรับเพื่อนๆคนไหนที่มีคำถามหรือมีอยากจะเสนอแนะนำ แชร์ไอเดียก็สามารถตั้งกระทู้เข้ามาได้เลยนะครับ

    เชื่อว่าเพื่อนๆพี่ๆน้องๆที่อยู่ที่นี่ รวมถึงทีมงานทุกคนพร้อมที่จะช่วยเหลือและแบ่งปันแน่นอนครับ

     

    ปล. ทีมงานได้รวมไฟล์ AFL ที่เกี่ยวข้องไว้ใน Link ด้านล่าง หากเพื่อนๆคนไหนสนใจก็โหลดไปได้เลยนะครับ

    Link >>> 52WH+MF SQDemo.zip

     

    ขอบคุณคุณ chaipod สำหรับคำถามด้วยนะครับ

    ขอบคุณครับ 😀

    #10191
    chaipod
    Participant

    เยี่ยมมากครับ…อธิบายได้ละเอียดมากๆ….ขอขอบคุณ..คุณ BlueStepz และทีมงานมากๆครับ…

    ข้อ1 และ 2 เดี๋ยวขอไปลองทำดู ถ้าติดปัญหาจะมาถามนะครับ….

    ส่วนข้อ3 ขอถามเพิ่มว่า เราสามารถใช้คำสั่ง StaticVarSet  เก็บชื่อหุ้นที่มีข้อมูลในช่วงที่เราจะ test ไว้ก่อน

    แล้วค่อยเรียกชื่อหุ้นชุดนี้มาจัด ranking ภายหลังโดยไม่ต้องสร้าง watchlist ใหม่ได้ไหมครับ….ขอบคุณครับ….

     

     

    #10195
    chaipod
    Participant

    ข้อที่1. backtest แล้วจะมี result เฉพาะ FirstDayofYear กับ LastDayofYear

    แต่พอเปลี่ยนเป็นวันอื่นก็จะไม่มี result ออกมาครับ

    dayShift = 2;
    PositionScore = IIf( Ref(lastDayofYear, dayShift), Score, scoreNoRotate );

    ลอง shift วันดูครับ จะได้เฉพาะ 0 กับ -1 แต่ค่าอื่นๆจะไม่ได้ครับ

    ขอบคุณครับ

    #10196
    Amibroker Platform
    Participant

    ผมยังไม่ได้ลอง code ชุดนี้ เเต่จากชุด Code ถูกเเล้วคับ เพราะมันย้อนกลับไป 1วันสุดท้ายของปีก่อน ถ้าใส่ 1 หรือ 2 ไม่มีค่าลบ มันจะพูดถึงอนาคตที่ยังไม่มีคับ

    #10198
    kaluu
    Participant

    ชื่นชม คุณ BlueStepz และทีมงานครับ ที่ตอบคำถามได้ละเอียดมากๆ

    ถ้าผมมีอาจารย์สอนแบบนี้ตอนเรียน ผมคงรู้เรื่องprograming มากขึ้นกว่านี้แน่ๆฮ่ะ 🙂

    #10199
    Amibroker Platform
    Participant

    กระทู้ดี เสียดายไม่มีสติ๊กเกอร์ให้กด 555+

กำลังดู 10 ข้อความตอบกลับ - 1 ผ่านทาง 10 (ของทั้งหมด 10)
  • คุณต้องเข้าสู่ระบบเพื่อตอบกลับกระทู้นี้

เราใช้คุกกี้เพื่อพัฒนาประสิทธิภาพ และประสบการณ์ที่ดีในการใช้เว็บไซต์ของคุณ คุณสามารถศึกษารายละเอียดได้ที่ นโยบายความเป็นส่วนตัว และสามารถจัดการความเป็นส่วนตัวเองได้ของคุณได้เองโดยคลิกที่ ตั้งค่า

ตั้งค่าความเป็นส่วนตัว

คุณสามารถเลือกการตั้งค่าคุกกี้โดยเปิด/ปิด คุกกี้ในแต่ละประเภทได้ตามความต้องการ ยกเว้น คุกกี้ที่จำเป็น

ยอมรับทั้งหมด
จัดการความเป็นส่วนตัว
  • เปิดใช้งานตลอด

บันทึกการตั้งค่า