3

開始日のリストと終了日のリストがあります。彼らは並べられています...

start_dates = [
    datetime.date(2009, 11, 5), datetime.date(2009, 11, 13), 
    datetime.date(2009, 11, 25), datetime.date(2009, 11, 26), 
    datetime.date(2009, 12, 4), datetime.date(2009, 12, 7), 
    datetime.date(2009, 12, 29), datetime.date(2009, 12, 30)]

end_dates = [
    datetime.date(2009, 10, 1), datetime.date(2009, 10, 2), 
    datetime.date(2009, 10, 9), datetime.date(2009, 10, 12), 
    datetime.date(2009, 11, 4), datetime.date(2009, 12, 14), 
    datetime.date(2009, 12, 15)]

開始日は、当社が株式購入のアドバイスを受けた日付を表しています。終了日は、売却のアドバイスを受けた日です。アドバイスのソースはさまざまであり、あるソースからの買いのアドバイスを使用し、別のソースからの売りのアドバイスを使用した場合に何が起こるかをバックテストしています. このように、2 つの一連の日付をペア (または間隔) に分解して、株式のポジションを保持したいと考えています。

したがって、start_dates から日付を取得して、いつ株を購入するかを決定します。11 月 5 日にポジションを購入します。次に end_dates を巡回して、最初の売却アドバイスを探します: 12 月 14 日です。そして、ある情報源からアドバイスされたときにポジションを保持していないときに購入し、別の情報源からポジションを保持しているときに売却することを繰り返します。

ループしている 2 つのリストのどちらの間でフラップしたいと言うかもしれません。

したがって、上記の入力により次が生成されます。

result = (
  (datetime.date(2009, 11, 5), datetime.date(2009, 12, 14)),
  (datetime.date(2009, 12, 29), None)
)

for ループ内で for ループを使用していますが、もっと良い方法はないのでしょうか。パフォーマンスは、40 年間にわたって何千ものシナリオに適用されるため、興味深いものです。リストの中には、何千もの日付が含まれているものもあります。

4

4 に答える 4

2

編集

これは次のようにスケーリングする必要がありlen(start_dates)+len(end_dates)ます。

def date_range(start_dates, end_dates):
    result = []

    start_i = 0
    end_i = 0

    while start_i<len(start_dates):
        while end_i<len(end_dates) and start_dates[start_i]>end_dates[end_i]:
            end_i += 1
        if end_i == len(end_dates):
            result.append((start_dates[start_i], None))
            break
        result.append((start_dates[start_i], end_dates[end_i]))
        while start_i<len(start_dates) and start_dates[start_i]<=end_dates[end_i]:
            start_i += 1
        end_i += 1

    return result

使用法:

In  : start_dates = [
   ....:     datetime.date(2009, 11, 5), datetime.date(2009, 11, 13),
   ....:     datetime.date(2009, 11, 25), datetime.date(2009, 11, 26),
   ....:     datetime.date(2009, 12, 4), datetime.date(2009, 12, 7),
   ....:     datetime.date(2009, 12, 29), datetime.date(2009, 12, 30)]

In : end_dates = [
   ....:     datetime.date(2009, 10, 1), datetime.date(2009, 10, 2),
   ....:     datetime.date(2009, 10, 9), datetime.date(2009, 10, 12),
   ....:     datetime.date(2009, 11, 4), datetime.date(2009, 12, 14),
   ....:     datetime.date(2009, 12, 15)]

In : date_range(start_dates, end_dates)
Out:
[(datetime.date(2009, 11, 5), datetime.date(2009, 12, 14)),
 (datetime.date(2009, 12, 29), None)]

In : start_dates = [
   ....:     datetime.date(2009, 11, 5), datetime.date(2009, 11, 13),
   ....:     datetime.date(2009, 11, 25), datetime.date(2009, 11, 26),
   ....:     datetime.date(2009, 12, 4), datetime.date(2009, 12, 7),
   ....:     datetime.date(2009, 12, 29), datetime.date(2009, 12, 30)]

In : end_dates = [
   ....:     datetime.date(2009, 10, 1), datetime.date(2009, 10, 2),
   ....:     datetime.date(2009, 10, 9), datetime.date(2009, 10, 12),
   ....:     datetime.date(2009, 11, 7), datetime.date(2009, 12, 14), # changed (2009, 11, 4) -> (2009, 11, 7)
   ....:     datetime.date(2009, 12, 15)]

In : date_range(start_dates, end_dates)
Out:
[(datetime.date(2009, 11, 5), datetime.date(2009, 11, 7)),
 (datetime.date(2009, 11, 13), datetime.date(2009, 12, 14)),
 (datetime.date(2009, 12, 29), None)]
于 2012-08-24T04:35:31.050 に答える
1

私は最終的にそれを釘付けにしました:

    trades = []
    enddate = datetime.date(1900, 1, 1)
    try:
        for startdate in startdates:
            if enddate <= startdate:
                enddate = enddates.next()
                while enddate <= startdate:
                    enddate = enddates.next()
                trades.append((startdate, enddate))
    except StopIteration:
        trades.append((startdate, None))

質問して答えてくれた人に感謝します。理にかなった理由もなく、この小さなパズルは私を夢中にさせましたが、ついに私はこれを死ぬまでやったので、私の人生を続けるべきだと思います. 結局のところ、これは非常に単純です。これを単純化するのにどれだけの作業が必要だったかに驚かされます。

于 2012-08-25T06:38:44.227 に答える
1

これは日付のタプルを取得するために機能すると思いますが、 for ループを使用せずに方法を提案することはできません。代わりに、より複雑になる可能性があるためです。

ただし、ロジックは非常に単純で明白です。

result = []
for startd in start_dates:
    if not result or result[-1][1] is not None and startd>result[-1][1]:
    #can use 'len(result)==0' instead of 'not result'
        for endd in end_dates:
            if endd>startd:
                result.append((startd,endd))
                break
        else:
            result.append((start,None))
    if result[-1][1] is None:
        break

result = tuple(result)
print result
于 2012-08-24T06:35:56.573 に答える
0

これはどう。

all_dates = start_dates.expand(end_dates)
all_dates.sort()

look_for_start = 1;
date = []
start_date = None
end_date = None
for i in range(len(all_dates)):
   if look_for_start and all_dates[i] in start_dates:
     start_date = all_dates[i]
     look_for_start = 0;

   elsif !look_for_start and all_dates[i] in end_dates:
     end_date = all_dates[1]
     look_for_start = 1;

   if start_date == end_date:
     end_date == None
     look_for_start = 0;

   if start_date != None and end_date != None;
     date.append((start_date,end_date))
     start_date = None
     end_date = None

この後、可能な限り終了日を含む start_dates があります。start_dates の残りのセットを取得し、終了日を None に設定するだけです

于 2012-08-24T03:59:13.317 に答える