COCO研究院

 找回密碼
 註冊
搜索
查看: 4388|回復: 3

[範例程式碼] 不同視窗同步捲動縮放

[複製鏈接]
發表於 12-11-26 23:16 | 顯示全部樓層 |閱讀模式
本帖最後由 zaqimon 於 12-11-26 23:14 編輯

之前已經有回覆別的文章
我又稍微修改一下程式
加入ZoomRatio變數控制主視窗及被控制視窗之間的顯示日數比例
例如日線及周線就設定ZoomRatio=5就可以顯示幾乎同比例的bar數量
在日線以上週期的視窗之間運作基本上都沒有什麼大問題

我還有嘗試加入台指期1min/5min的同步
請在include之前自行加入TaifexHack = 1;
ZoomRatio也設成5
順順的用習慣的話應該是還堪用啦
但其實我發現問題還蠻多的
目前程式裡面先假設所有周末都不是交易日直接跳過
如果大家有更好的做法可以自行修改

2012-11-26_223309.gif

請將最下方AFL放到Include資料夾內且命名為iZoomer.afl
然後在你希望控制連動的主視窗內加入下面程式碼即可
  1. UseZoomer = ParamToggle("Use Zoomer?", "No|Yes", 0);
  2. ZoomRatio = Param("Zoomer ZoomRatio", 5, 0.1, 10, 0.1);
  3. //TaifexHack = 1;
  4. #include_once <iZoomer.afl>
複製代碼

iZoomer.afl
  1. /*

  2. Synchronous scrolling on all windows in AmiBroker

  3. <Usage>
  4. Put this AFL in the Include Folder.
  5. Add below lines into your AFL
  6.   UseZoomer = ParamToggle("Use Zoomer?", "No|Yes", 0);
  7.   ZoomRatio = Param("Zoomer ZoomRatio", 1, 0.1, 10, 0.1); // 5 is a good ratio for daily/weekly pair
  8.   // TaifexHack = 1; // work around for Taifex intraday 1min/5min pair
  9.   #include_once <iZoomer.afl>


  10. [20121126] zaqimon
  11. Add ZoomRatio for showing multiple(x2, x5, x0.7, ...) of current window view range
  12. TaifexHack=1, still not perfect, because it is hard to 'jump' those non trading period. Is there any better idea?


  13. [20120915] zaqimon
  14. original AFL from htt[delete me]p:/[delete me]/finance.groups.yahoo.com/group/amibroker/message/141912
  15. I did a slight modification.

  16. */

  17. function Date2Day( wd_dt) /* convert date to weekday */
  18. {
  19.     wd_datenum = DateTimeConvert(0, (wd_dt));
  20.     wd_c = int( wd_datenum / 100 / 100 / 100 + 19); // datenum start from 1900
  21.     wd_y = int((wd_datenum / 100 / 100) % 100);
  22.     wd_m = int((wd_datenum / 100) % 100);
  23.     wd_d = int( wd_datenum % 100);
  24.     // if Jan., Feb., assume it to be last year's 13th, 14th month.
  25.     if(wd_m<=2)
  26.     {
  27.         wd_m += 12;
  28.         wd_y -= 1;
  29.     }
  30.     // w = (y+[y/4]+[c/4]-2c+[26(m+1)/10]+d-1) mod 7
  31.     // formula from htt[delete me]p:/[delete me]/zh.wikipedia.org/wiki/%E8%94%A1%E5%8B%92%E5%85%AC%E5%BC%8F
  32.     wd_w = wd_y + int(wd_y / 4) + int(wd_c / 4) - 2 * wd_c + int(26 * (wd_m + 1) / 10) + wd_d - 1;
  33.     wd_w = ((wd_w % 7) + 7) % 7; // if -5, -12, -19, ... , make it to be +2
  34.     return int(wd_w); // 0:Sun, 1:Mon, ...
  35. }

  36. function ZqZoomSync( force )
  37. {
  38.     global ZoomRatio;
  39.     local LastBarIndex, FirstBarIndex, prevLastBarIndex, prevFirstBarIndex, prevFirstDateTime, DT, BI, LastDateTime, FirstDateTime, LastDateTimestr, FirstDateTimestr;
  40.     local reuseLastDTDiff, DTDiff;
  41.     local OAB, OAD, dcount, i, OADoc, OAW, OADocWin, res;
  42.     // Get a count of the number of documents
  43.     OAB = CreateObject( "Broker.Application" );
  44.     OAD = OAB.Documents;
  45.     dcount = OAD.Count;
  46.     // Process multiple windows (documents)
  47.     res = False;
  48.     if ( dcount > 1 )
  49.     {
  50.         // Get current and last start and end DateTimes's
  51.         LastBarIndex = Status( "LastVisibleBarIndex" );
  52.         FirstBarIndex = Status( "FirstVisibleBarIndex" );
  53.         //Nblankbar = Status( "LastVisibleBarIndex" ) - BarCount; // [zq] not used !!
  54.         
  55.         // [zq] BarIndex may always be the same due to QuickAFL, check prevFirstDateTime in addition
  56.         prevLastBarIndex = Nz( StaticVarGet( "_prevLastVisibleBarIndex" ) );
  57.         prevFirstBarIndex = Nz( StaticVarGet( "_prevFirstVisibleBarIndex" ) );
  58.         prevFirstDateTime = Nz( StaticVarGet( "_prevFirstDateTime" ) );
  59.         prevDTDiff = Nz( StaticVarGet( "_prevDTDiff" ) );
  60.         
  61.         // use this to prevent changing zoom range if bar counts in current window not changed,
  62.         // or you may see bars in other windows quiver back and forth while scrolling
  63.         reuseLastDTDiff = False;
  64.         if(prevLastBarIndex-prevFirstBarIndex == LastBarIndex-FirstBarIndex AND prevDTDiff != 0)
  65.         {
  66.             reuseLastDTDiff = True;
  67.         }
  68.         
  69.         // [zq] move outside if() statement for checking prevFirstDateTime
  70.         DT = DateTime();
  71.         BI = BarIndex();
  72.         LastDateTime = LastValue( ValueWhen( LastBarIndex == BI, DT ) ); // [zq] LastDateTime could be empty
  73.         FirstDateTime = LastValue( ValueWhen( FirstBarIndex == BI, DT ) );
  74.         
  75.         // Check for a new date/time range
  76. //        _TRACE(""+FirstBarIndex+", "+LastBarIndex);
  77. //        _TRACE(""+FirstDateTime+", "+LastDateTime);
  78.         if ( LastBarIndex != prevLastBarIndex OR FirstBarIndex != prevFirstBarIndex OR FirstDateTime != prevFirstDateTime OR force )
  79.         {

  80.             LastDateTimestr = DateTimeToStr( LastDateTime );
  81.             DTDiff = DateTimeDiff(LastDateTime, FirstDateTime); // in second
  82.             if(reuseLastDTDiff)
  83.             {
  84.                 DTDiff = prevDTDiff;
  85.             }
  86.             if(typeof(ZoomRatio) != "number")
  87.             {
  88.                 ZoomRatio = 1; // default ZoomRatio
  89.             }
  90.             FirstDateTimestr = DateTimeToStr(DateTimeAdd(LastDateTime, -ZoomRatio * DTDiff, in1Second));
  91.             
  92.             if(typeof(TaifexHack) == "number" AND TaifexHack==1) // Taifex intraday hack, but still not perfect
  93.             {
  94.                 tn = DateTimeConvert(1, StrToDateTime(FirstDateTimestr));
  95.                 if(tn < 084500)
  96.                 {
  97.                     FirstDateTimestr = DateTimeToStr(DateTimeAdd(LastDateTime, -ZoomRatio * DTDiff - 19*3600, in1Second)); // try to 'jump' non trading hours
  98.                     wd = Date2Day(StrToDateTime(FirstDateTimestr));
  99.                     // assume weekend non trading days, 'jump', of course this is not perfect solution
  100.                     if(wd == 0)
  101.                     {
  102.                         FirstDateTimestr = DateTimeToStr(DateTimeAdd(LastDateTime, -ZoomRatio * DTDiff - 19*3600 - 2*24*3600, in1Second));
  103.                     }
  104.                 }
  105.             }

  106.             // Set the new last values
  107.             StaticVarSet( "_prevLastVisibleBarIndex", LastBarIndex );
  108.             StaticVarSet( "_prevFirstVisibleBarIndex", FirstBarIndex );
  109.             StaticVarSet( "_prevFirstDateTime", FirstDateTime );
  110.             StaticVarSet( "_prevDTDiff", DTDiff );
  111.             
  112. //            _TRACE(""+FirstDateTimestr+", "+LastDateTimestr);
  113.             // Loop through the document collection
  114.             for ( i = 0; i < dcount; i++ )
  115.             {
  116.                 // If it is not the active document -
  117.                 OADoc = OAD.Item( i );
  118.                 // NOTE - it doesn't hurt to sync the current window and it makes all
  119.                 // windows have no blank bars on the right so they look the same
  120.                 // [zq] I think it's reasonable for not syncing ActiveDocument.
  121.                 // [zq] Something not belong to the ActiveDocument was shown when not syncing ActiveDocument with multi-threaded charts options disabled.
  122.                 if ( OADoc != OAB.ActiveDocument )
  123.                 {
  124.                     // Get the document window and zoom to range
  125. //                    _TRACE( " Zoom to range document - " + i + " , " + FirstDateTimestr + " - " + LastDateTimestr );
  126.                     OADW = OADoc.Windows;
  127.                     // Document window count assumed to be 1
  128.                     OADocWin = OADW.Item( 0 );
  129.                     OADocWin.ZoomToRange( FirstDateTimestr, LastDateTimestr ); // [zq] this function failed to update chart at the right most margin with empty LastDateTimestr. Just minor issue, don't care.
  130.                 }
  131.             }
  132.             res = True;
  133.         }
  134.     }
  135.     return res;
  136. }

  137. //  Call for synchronization
  138. If (UseZoomer)
  139.      ZqZoomSync( False ); // [zq] set True will enter infinite loop if we also update ActiveDocument
複製代碼







補充內容 (12-12-20 11:32):
補充程式碼在三樓

評分

參與人數 3金錢 +11 收起 理由
仔仔 + 2 很棒的文章,感恩!
kilroy + 5 按一個讚!
hipper68 + 4 按一個讚!

查看全部評分

發表於 12-11-26 23:47 | 顯示全部樓層
真的太讚了...
一定要推一下...

謝謝大大的分享...
 樓主| 發表於 12-12-20 11:32 | 顯示全部樓層
在第83行處插入下面的程式碼
避免LastDateTime為0的狀況
這樣就算捲動到畫面最右邊blank bar的地方也都還能夠同步
  1. // make sure LastDateTime non-zero.
  2.         if(DateTimeDiff(LastDateTime,FirstDateTime)<0) // roll back to the last non-empty bar index
  3.         {
  4.             for(i=BarCount-1; i>0; i--) // all array has BarCount size, BI[i] value has nothing to do with BarCount
  5.             {
  6.                 if(DateTimeDiff(DT[i],FirstDateTime)>0) // we saw the REAL last bar, replace the values.
  7.                 {
  8.                     LastBarIndex = BI[i];
  9.                     LastDateTime = DT[i];
  10.                     break;
  11.                 }
  12.             }
  13.         }
複製代碼
發表於 16-12-3 08:54 | 顯示全部樓層
為何他是不通過的???
2016-12-03_085303.png
您需要登錄後才可以回帖 登錄 | 註冊

本版積分規則

手機版|Archiver|站長信箱|廣告洽詢|COCO研究院

GMT+8, 24-11-22 23:34

Powered by Discuz! X3.4

Copyright © 2001-2023, Tencent Cloud.

快速回復 返回頂部 返回列表
理財討論網站 |